/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XSCBaseStrategy // Description: provides all based classes for use ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // /// Imports ... #include "../Libraries/x-saherelm.tools.lib.mq5" #include "../Classes/x-saherelm.xtrade.class.mq5" #include "../Classes/x-saherelm.xalert.class.mq5" // // Definitions ... // enum ENUM_X_SIGNALLING_DIRECTION { X_SIGNALLING_NONE = 0, X_SIGNALLING_BOTH_DIRECTIONS = 1, X_SIGNALLING_TREND_DIRECTION = 2, X_SIGNALIING_TREND_REVERSAL_DIRECTION = 3 }; // class XSCBaseStrategy : public XSCBaseAlert { // // Public ... public: // // Constructors ... void XSCBaseStrategy( string _symbol, // Trading Symbol ENUM_TIMEFRAMES _period, // Trading TimeFrame double _volume, // Voluem double _r2r, // Risk/Reward Ratio int _slippage, // Trader Slippage long _magicNumber, // Trader Magic Number bool _ignoreSignalExecution = false, // Ignore Signal Execution bool _useTPSLAsPoint = false, // Converts TP and SL by Provided Points bool _forceMaxTPSLAsPoint = false, // Force Max TP and SL by Provided Points double _tpPoint = 0, // TP As Point double _slPoint = 0, // SL As Point bool _ignoreTP = false, // TP set to 0 bool _ignoreSL = false, // SL set to 0 bool _allowLong = true, bool _allowShort = true, int _maxAllowedLongs = 0, int _maxAllowedShorts = 0 // ) { // // Fill Properties ... mR2R = _r2r; mVolume = _volume; mSymbol = _symbol; mPeriod = _period; mTPPoint = _tpPoint; mSLPoint = _slPoint; mIgnoreTP = _ignoreTP; mIgnoreSL = _ignoreSL; mSlippage = _slippage; mAllowLong = _allowLong; mAllowShort = _allowShort; mMagicNumber = _magicNumber; mUseTPSLAsPoint = _useTPSLAsPoint; mMaxAllowedLongs = _maxAllowedLongs; mMaxAllowedShorts = _maxAllowedShorts; mForceMaxTPSLAsPoint = _forceMaxTPSLAsPoint; mIgnoreSignalExecution = _ignoreSignalExecution; // mForceDisabled = false; // // Initial Trader Class Instance ... trader = new XSCTrade( mSlippage, mMagicNumber // ); // // Initial Time Tracker ... barTracker.Init( mSymbol, mPeriod // ); // SetAlertPrefix(GetTag()); } // // Deconstructor ... void ~XSCBaseStrategy() { // delete trader; // Reset(); } // // Getter and Setter (s) ... // int Slippage() { return mSlippage; } // long MagicNumber() { return mMagicNumber; } // string Symbol() { return mSymbol; } // ENUM_TIMEFRAMES Period() { return mPeriod; } // bool IsDisabled() { return mForceDisabled; } // void Disable() { mForceDisabled = true; } // void Enable() { mForceDisabled = false; } // double Volume() { return mVolume; } // void Volume(double value) { // if (value < 0.01) { value = 0.01; } // mVolume = value; } // double R2R() { return mR2R; } // bool AllowLong() { return mAllowLong; } // void AllowLong(bool value) { mAllowLong = value; } // bool AllowShort() { return mAllowShort; } // void AllowShort(bool value) { mAllowShort = value; } // int MaxAllowedLongs() { return mMaxAllowedLongs; } // void MaxAllowedLongs(int value) { // if (value < 0) { value = 0; } // mMaxAllowedLongs = value; } // int MaxAllowedShorts() { return mMaxAllowedShorts; } // void MaxAllowedShorts(int value) { // if (value < 0) { value = 0; } // mMaxAllowedShorts = value; } // int RequiredPivots() { return mRequiredPivots; } // void RequiredPivots(int value) { // if (value < 3) { value = 3; } // mRequiredPivots = value; } // int RequiredShoulders() { return mRequiredShoulders; } // void RequiredShoulders(int value) { // if (value < 5) { value = 5; } // mRequiredShoulders = value; } // bool UseTPSLAsPoint() { return mUseTPSLAsPoint; } // void UseTPSLAsPoint(bool value) { mUseTPSLAsPoint = value; } // bool ForceMaxTPSLAsPoint() { return mForceMaxTPSLAsPoint; } // void ForceMaxTPSLAsPoint(bool value) { mForceMaxTPSLAsPoint = value; } // double TPPoint() { return mTPPoint; } // void TPPoint(double value) { // if (value < 0) { value = 0; } // mTPPoint = value; } // double SLPoint() { return mSLPoint; } // void SLPoint(double value) { // if (value < 0) { value = 0; } // mSLPoint = value; } // bool IgnoreTP() { return mIgnoreTP; } // void IgnoreTP(bool value) { mIgnoreTP = value; } // bool IgnoreSL() { return mIgnoreSL; } // void IgnoreSL(bool value) { mIgnoreSL = value; } // bool IgnoreSignalExecution() { return mIgnoreSignalExecution; } // void IgnoreSignalExecution(bool value) { mIgnoreSignalExecution = value; } // // On Signal Handlers ... void AddSignalEventHandler(TOnSignal handler) { // Add( handler, mOnSignalEventHandlers // ); } // // Virtual Methods ... // // Tag ... virtual string GetTag() { return "XBaseStrategy"; } // // Check Conditions for Signal ... // this must be Override based on each Strategy ... virtual bool HasSignal( XSignal &signal // ) { return false; } // // Check Conditions For Signal and Execute Signal ... virtual void HandleTick() { // if (IsDisabled()) { return; } // if (!AllowLong() && !AllowShort()) { return; } // if (!barTracker.CanProcessBar()) { return; } // MqlTick cTick; bool hasTick = GetTick( mSymbol, cTick // ); bool isSameAsLast = cTick.time == lastTick.time; if (isSameAsLast) { return; } // lastTick = cTick; // XSignal signal; bool hasSignal = HasSignal(signal); if (!hasSignal) { return; } // barTracker.Waits(); // Execute(signal); } // // Handle Signal Execution ... virtual bool Execute(XSignal &signal) { // bool result = false; // result = !IsDisabled(); if (!result) { return result; } // result = signal.IsValid(); if (!result) { return result; } // bool isLong = IsLong(signal.type); // result = // isLong ? AllowLong() : AllowShort() // ; if (!result) { return result; } // // Check Max Allowed Trades Limitation ... if ( (isLong && MaxAllowedLongs() > 0) || (!isLong && MaxAllowedShorts() > 0)) { // // Here We Have to Count Positions ... // // Get and Count Positions ... XPosition positions[]; int positionsCount = trader.GetPositions( positions // ); // // Get and Count Lng and Short Positions ... XPosition longs[]; XPosition shorts[]; ExtractPositions( positions, longs, shorts // ); int longsCount = ArraySize(longs); int shortsCount = ArraySize(shorts); // result = // isLong ? longsCount < MaxAllowedLongs() : shortsCount < MaxAllowedShorts() // ; if (!result) { return result; } } // // Check TP and SL ... double points = GetPoints(signal.symbol); if (mUseTPSLAsPoint) { // double sl = 0; double tp = 0; bool isCalculated = !(mSLPoint > 0 || mTPPoint > 0) ? false : CalculateTPSLByPoint( sl, tp, signal.type, signal.entry, points, mR2R, mSLPoint, mTPPoint // ); if (isCalculated) { // signal.sl = sl; signal.tp = tp; } } else if (mForceMaxTPSLAsPoint) { // if (mSLPoint > 0) { // double risk = signal.GetRisk(); double riskPoints = risk / points; // if (riskPoints > mSLPoint) { // signal.sl = isLong ? signal.entry - (mSLPoint * points) : signal.entry + (mSLPoint * points); } } // if (mTPPoint > 0) { // double reward = signal.GetReward(); double rewardPoints = reward / points; // if (rewardPoints > mTPPoint) { // signal.tp = isLong ? signal.entry + (mTPPoint * points) : signal.entry - (mTPPoint * points); } } } // if (mIgnoreTP) { signal.tp = 0; } // if (mIgnoreSL) { signal.sl = 0; } // // Notify Signal Event Handler(s) ... NotifyOnSignalEventHandlers(signal); // // Check Signal Execution Enabled or not ... result = !mIgnoreSignalExecution; if (!result) { return result; } // ENUM_X_SIGNAL_EXECUTION_RESULT state; result = trader.ExecuteSignal( signal, state // ); if (result) { // string message = "Execute " + (isLong ? "Long" : "Short") + " " + signal.symbol + "/" + ToString(signal.period) + " ..."; Alert(message); // OnSignalExecuted(signal); } else { OnSignalExecutionFailed(signal, state); } // return result; } // // Calls When a Signal Executed Successfully ... virtual void OnSignalExecuted(XSignal &signal) { } // // Calls When a Signal Execution Failed ... virtual void OnSignalExecutionFailed( XSignal &signal, ENUM_X_SIGNAL_EXECUTION_RESULT result // ) { } // // Protected ... protected: // int mSlippage; // Trader Slippage long mMagicNumber; // Trader Magic Number bool mForceDisabled; // Force Disabled bool mAllowLong; // Allow Long Signals bool mAllowShort; // Allow Short Signals int mMaxAllowedLongs; // Max Allowed Longs int mMaxAllowedShorts; // Max Allowed Shorts // bool mUseTPSLAsPoint; // Converts TP and SL by Provided Points bool mForceMaxTPSLAsPoint; // Force Max TP and SL by Provided Points double mTPPoint; // TP As Point double mSLPoint; // SL As Point bool mIgnoreTP; // TP set to 0 bool mIgnoreSL; // SL set to 0 bool mIgnoreSignalExecution; // Ignore Signal Execution // string mSymbol; // Trading Symbol ... ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame ... // double mR2R; // Risk/Rewar Ratio ... double mVolume; // Static Volume Per Trades ... // XBarTracker barTracker; // Strategy Time Tracker ... // // Trend Detecting ... int mRequiredPivots; // Required Pivots For Trend Detecting ... int mRequiredShoulders; // Required Pivots Shoulders ... // XSCTrade *trader; // MqlTick lastTick; // void Reset() { barTracker.Clean(); } // // Notified Signal Event Handler(s) ... void NotifyOnSignalEventHandlers(XSignal &signal) { // if (!signal.IsValid()) { return; } // int count = ArraySize(mOnSignalEventHandlers); if (!IsValidSize(count)) { return; } // for (int i = 0; i < count; i++) { mOnSignalEventHandlers[i](signal); } } // // Private ... private: // // Props ... // // On Signal Recieved Event Handler(s) ... TOnSignal mOnSignalEventHandlers[]; }; //