/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // ---------------------------------------------- // Name: XSCX121SetupCycle // Description: provides implementation of X121 // Setup on Specified Market Cycle ... // // // 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 "../Classes/x-saherelm.xea.class.mq5" #include "../Classes/x-saherelm.x121.setup.cycle.class.mq5" // // Definitions ... // struct XSignalInfo { // ulong ticket; // Position Ticket string symbol; // Trading Symbol string provider; // Signaller int pushers; // Signal Pushers ENUM_TIMEFRAMES period; // Trading Timeframe datetime time; // Issue Time (Open Position) // double profit; // Profit on Close datetime endTime; // End Time string message; // Close Reason // double bullishScore; // Bullish Score On Signal Time double bearishScore; // Bearish Score On Signal Time // XSignal signal; // Generated Signal X121SetupConditions conditions; // Generated Conditions // // Constructor ... void XSignalInfo() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // ticket = 0; symbol = NULL; period = NULL; time = NULL; profit = 0; endTime = NULL; message = NULL; bullishScore = 0; bearishScore = 0; signal.Clean(); conditions.Clean(); } // bool Fill( int _pushers, XSignal &_signal, X121SetupConditions &_conditions // ) { // bool result = false; // result = // IsValid(_signal.symbol) && IsValid(_signal.period) && IsValid(_signal.provider) // ; // if (!result) { return result; } // pushers = _pushers; symbol = _signal.symbol; period = _signal.period; provider = _signal.provider; // signal = _signal; conditions = _conditions; // return result; } // bool IsOwn( ulong _ticket // ) { // bool result = false; // result = _ticket == ticket; // return result; } // bool IsOwn( string _symbol, string _provider, ENUM_TIMEFRAMES _period // ) { // bool result = false; // result = // IsValid(_symbol) && IsValid(_provider) && IsValid(_period) && // symbol == _symbol && provider == _provider && period == _period // ; // return result; } // // Data Collector ... // bool IsValid() { // bool result = false; // result = // ticket > 0 && IsValid(time) && IsValid(symbol) && IsValid(period) // ; // return result; } // string GetFileName() { // string result = NULL; // if (!IsValid()) { return result; } // result = // symbol + "_" + provider + "_" + ToString(ticket) + "_" + ToString(period) + "_" + ToString(time) // ; // return result; } // string ToModelString() { // string result = NULL; // string conditionsStr = conditions .GenerateSummary( false, // Only Commons ... true, // Only Conditions ... false, // Include Score ... false // Include False Conditions ...ّ ); // result = // ToString("Ticket", ticket) + ToString("Symbol", symbol) + ToString("Period", period) + ToString("Time", time) + ToString("BullishScore", bullishScore) + ToString("BearishScore", bearishScore) + ToString("Profit", profit) + ToString("End Time", endTime) + ToString("Message", message) + "-------------" + "\n" + ToString("Signal", signal.ToModelString()) + ToString("Conditions", conditionsStr) + // "" // ; // return result; } // }; // class XSignalInfoCollector { // // Public ... public: // // Props ... // // Constructor(s) ... void XSignalInfoCollector( string _path = NULL // Base Path ) { // if (IsValid(_path)) { mPath = _path; } else { mPath = "XSignalInfo"; } } // // Deconstructor ... void ~XSignalInfoCollector() {} // bool IsExists(XSignalInfo &item) { // bool result = false; // int mHandler = GetFileHandlerForRead(item); result = mHandler != INVALID_HANDLE; FileClose(mHandler); // return result; } // bool Save(XSignalInfo &item) { // bool result = false; // // Check info is Valid ... result = item.IsValid(); if (!result) { return result; } // string content = item.ToModelString(); result = IsValid(content); if (!result) { return result; } // int mHandler = GetFileHandlerForWrite(item); result = mHandler != INVALID_HANDLE; if (!result) { return result; } // FileWrite(mHandler, content); FileFlush(mHandler); FileClose(mHandler); // return result; } // // Protected ... protected: // // Private ... private: // // Props ... // string mPath; // Base Path ... // string GetFilePath(XSignalInfo &item) { // string fileName = item.GetFileName(); // return GetFilePath(fileName); } string GetFilePath(string fileName) { // string result = ""; // result = // mPath + "\\" + fileName // ; // return result; } // int GetFileHandlerForRead(XSignalInfo &item) { // int result = INVALID_HANDLE; // string filePath = GetFilePath(item); if (!IsValid(filePath)) { return result; } // result = FileOpen( filePath, FILE_READ | FILE_TXT // ); // return result; } int GetFileHandlerForWrite(XSignalInfo &item) { // int result = INVALID_HANDLE; // string filePath = GetFilePath(item); if (!IsValid(filePath)) { return result; } // result = FileOpen( filePath, FILE_READ | FILE_WRITE | FILE_TXT // ); // return result; } }; // // Class ... class XSCX121SetupEA : public XSCBaseEA { // // Public ... public: // // Props ... // // Constructors ... XSCX121SetupEA( // // XTrade Class Requirements ... int slippage, // Specify Slippage ulong magicNumber, // Specify Magic Number // // XSCTrade Event Handlers ... TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler TOnTradeStateChanged onTradeStateChangedHandler = NULL // On Trade State Changed Event Handler ) : XSCBaseEA(slippage, magicNumber, onStopLossTriggered, onTakeProfitTriggered, onDealsChangedHandler, onOrdersChangedHandler, onPositionsChangedHandler, onTradeStateChangedHandler // ) { // Clean(mSignalInfos); mSignalCollector = new XSignalInfoCollector(); } // // Deconstructor ... ~XSCX121SetupEA() { } // bool AddSetup(XSCX121SetupCycles *setup) { // bool result = false; // result = setup != NULL; if (!result) { return result; } // Add( setup, mSetups // ); // return result; } // // Getter(s) / Setter(s) ... // bool AllowLong() { return mAllowLong; } // void AllowLong(bool value) { mAllowLong = value; } // bool AllowShort() { return mAllowShort; } // void AllowShort(bool value) { mAllowShort = value; } // bool IsEnable() { return mAllowLong || mAllowShort; } // // Overrides ... // // Customize Token ... string GetToken() override { return GetSpecificToken(this); } // string GetTag() override { return this.GetToken(); } // // Check Provider for any Guards ... bool CheckForGuard(XGuard &guards[]) override { // bool result = false; // return result; } // // Request Provider to Collect all // Potentially Signals and then // filters theme here and passed them // for Executing ... int RequestForSignal( XSignal &signals[] // Holds Signals ... ) override { // bool result = 0; // Clean(signals); // if (!IsEnable()) { return result; } // // IMPLEMENT ... int count = CountSetups(); result = IsValidSize(count); if (!result) { return result; } // string separator = "\n"; // X121SetupConditions cConditions; X121SetupConditions sConditions; X121SetupConditions mConditions; X121SetupConditions lConditions; X121SetupConditions hConditions; // XSignal cSignal; XSignal sSignal; XSignal mSignal; XSignal lSignal; XSignal hSignal; // int cPusher = 0; int sPusher = 0; int mPusher = 0; int lPusher = 0; int hPusher = 0; // X121SignalGenerator signalGenerator; // for (int i = 0; i < count; i++) { // // Cleanup Signals ... cSignal.Clean(); sSignal.Clean(); mSignal.Clean(); lSignal.Clean(); hSignal.Clean(); // // Current ... bool canProcess = mSetups[i] .CanProcessBar( X_MARKET_CYCLE_UNKNOWN // ); if (canProcess) { // bool iHasConditions = mSetups[i].GetConditions( cConditions, X_MARKET_CYCLE_UNKNOWN, // Current Market ... 0, // Bar Index ... 5 // Loop Back ... ); // if (!iHasConditions) { continue; } // mBullishScore = 0; mBearishScore = 0; // // Retrieve Scores ... double bullishScore = 0; double bearishScore = 0; cConditions.GenerateScore( bullishScore, bearishScore // ); mBullishScore += bullishScore; mBearishScore += bearishScore; // // Parse Conditions for Signal ... bool hasSignal = signalGenerator.HasSignal( cConditions, cSignal, cPusher, mAllowLong, mAllowShort // ); // if (hasSignal) { // mSetups[i].WaitsUntilNextBar( X_MARKET_CYCLE_UNKNOWN // ); } } // // Short ... canProcess = mSetups[i] .CanProcessBar( X_MARKET_CYCLE_SHORT // ); if (canProcess) { // bool iHasConditions = mSetups[i].GetConditions( sConditions, X_MARKET_CYCLE_SHORT, // Current Market ... 0, // Bar Index ... 5 // Loop Back ... ); // if (!iHasConditions) { continue; } // // Retrieve Scores ... double bullishScore = 0; double bearishScore = 0; sConditions.GenerateScore( bullishScore, bearishScore // ); mBullishScore += bullishScore; mBearishScore += bearishScore; // // Parse Conditions for Signal ... bool hasSignal = signalGenerator.HasSignal( sConditions, sSignal, sPusher, mAllowLong, mAllowShort // ); // if (hasSignal) { // mSetups[i].WaitsUntilNextBar( X_MARKET_CYCLE_SHORT // ); } } // // Medium ... canProcess = mSetups[i] .CanProcessBar( X_MARKET_CYCLE_MEDIUM // ); if (canProcess) { // bool iHasConditions = mSetups[i].GetConditions( mConditions, X_MARKET_CYCLE_MEDIUM, // Current Market ... 0, // Bar Index ... 5 // Loop Back ... ); // if (!iHasConditions) { continue; } // // Retrieve Scores ... double bullishScore = 0; double bearishScore = 0; mConditions.GenerateScore( bullishScore, bearishScore // ); mBullishScore += bullishScore; mBearishScore += bearishScore; // // Parse Conditions for Signal ... bool hasSignal = signalGenerator.HasSignal( mConditions, mSignal, mPusher, mAllowLong, mAllowShort // ); // if (hasSignal) { // mSetups[i].WaitsUntilNextBar( X_MARKET_CYCLE_MEDIUM // ); } } // // Long ... canProcess = mSetups[i] .CanProcessBar( X_MARKET_CYCLE_LONG // ); if (canProcess) { // bool iHasConditions = mSetups[i].GetConditions( lConditions, X_MARKET_CYCLE_LONG, // Current Market ... 0, // Bar Index ... 5 // Loop Back ... ); // if (!iHasConditions) { continue; } // // Retrieve Scores ... double bullishScore = 0; double bearishScore = 0; lConditions.GenerateScore( bullishScore, bearishScore // ); mBullishScore += bullishScore; mBearishScore += bearishScore; // // Parse Conditions for Signal ... bool hasSignal = signalGenerator.HasSignal( lConditions, lSignal, lPusher, mAllowLong, mAllowShort // ); // if (hasSignal) { // mSetups[i].WaitsUntilNextBar( X_MARKET_CYCLE_LONG // ); } } // // Hind ... canProcess = mSetups[i] .CanProcessBar( X_MARKET_CYCLE_HIND // ); if (canProcess) { // bool iHasConditions = mSetups[i].GetConditions( hConditions, X_MARKET_CYCLE_HIND, // Current Market ... 0, // Bar Index ... 5 // Loop Back ... ); // if (!iHasConditions) { continue; } // // Retrieve Scores ... double bullishScore = 0; double bearishScore = 0; hConditions.GenerateScore( bullishScore, bearishScore // ); mBullishScore += bullishScore; mBearishScore += bearishScore; // // Parse Conditions for Signal ... bool hasSignal = signalGenerator.HasSignal( hConditions, hSignal, hPusher, mAllowLong, mAllowShort // ); // if (hasSignal) { // mSetups[i].WaitsUntilNextBar( X_MARKET_CYCLE_HIND // ); } } } // // Parse Signals and Add them for Executing ... // Here we can Save Signal and it's Conditions to // Specified Collector then Update them on SL and TP ... // // Current Signals ... if (cPusher > 0 && cSignal.IsValid()) { // AddRef( cSignal, signals // ); // AddNewSignal( cPusher, cSignal, cConditions // ); } // // Short Signals ... if (sPusher > 0 && sSignal.IsValid()) { // AddRef( sSignal, signals // ); // AddNewSignal( sPusher, sSignal, sConditions // ); } // // Medium Signals ... if (mPusher > 0 && mSignal.IsValid()) { // AddRef( mSignal, signals // ); // AddNewSignal( mPusher, mSignal, mConditions // ); } // // Long Signals ... if (lPusher > 0 && lSignal.IsValid()) { // AddRef( lSignal, signals // ); // AddNewSignal( lPusher, lSignal, lConditions // ); } // // Hind Signals ... if (hPusher > 0 && hSignal.IsValid()) { // AddRef( hSignal, signals // ); // AddNewSignal( hPusher, hSignal, hConditions // ); } // // Create Score Summary for Commenting on Chart ... string scoreSummary = // "Scores:" + separator + "----------" + separator + "Bullish: " + ToString(mBullishScore) + separator + "Bearish: " + ToString(mBearishScore) + separator + "" // ; // Comment(scoreSummary); // result = ArraySize(signals); // return result; } // // Here we Manage Signals for Executing ... // - Check Policies based on their Signaller ... // - Check Same Time Open Positions ... // - Check Signal Age for new Trade ... // and etc ... int HandleSignalManagement(XSignal &signals[]) override { // int result = 0; // int signalsCount = ArraySize(signals); if (!IsValidSize(signalsCount)) { return result; } // XSignal tmpSignals[]; Copy( signals, tmpSignals // ); // Clean(signals); // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = tmpSignals[i]; // AddRef( iSignal, signals // ); } // result = ArraySize(signals); // return result; } // // Handle State Management .... // here we can manage current state ... // - Check for Long Positions for each Signaller to Close ... // - Handle Hedging Signaller's Positions if it's enabled ... // - Force Closing Position when Specified Time reached ... // - Check Start and End time or Trading Dates ... // - handle Trailing or Risk free Signals based on several conditions ... // and etc ... bool HandleStateManagement(XSignal &signals[]) override { // const bool result = false; // // Here we Implement Account Protector ... HandleAccountProtect(); // // Do all State Management here ... // // if Returns true, Signal Execution failed ... return result; } // // Tools For Signal Info Collect ... // void OnDealsChangedHandler(int count) { // XDeal deal; bool hasDeal = mTrader.GetLastDeal(deal); if (hasDeal) { UpdateSignalState(deal); } } // // Protected ... protected: // // Tools ... // // Do All Protection Senarios here ... void HandleAccountProtect() { } // // Private ... private: // // Props ... // bool mAllowLong; // Allow Long bool mAllowShort; // Allow Short // // TODO: // Add Volume and TP SL Points as Properties here ... // XSignalInfo mSignalInfos[]; XSignalInfoCollector *mSignalCollector; // int CountSignalInfos() { return ArraySize(mSignalInfos); } // int FindSignalInfoIndex( ulong positionTicket // ) { // int result = -1; // int count = CountSignalInfos(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XSignalInfo iInfo = mSignalInfos[i]; // bool isOwn = iInfo.IsOwn( positionTicket // ); if (isOwn) { // result = i; break; } } // return result; } // int FindSignalInfoIndex( string symbol, string provider, ENUM_TIMEFRAMES period // ) { // int result = -1; // int count = CountSignalInfos(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XSignalInfo iInfo = mSignalInfos[i]; // bool isOwn = iInfo.IsOwn( symbol, provider, period // ); if (isOwn) { // result = i; break; } } // return result; } // int FindSignalInfoIndex(XDeal &deal) { // int result = -1; // if (!deal.IsValid()) { return result; } // if (IsValid(deal.provider)) { result = FindSignalInfoIndex( deal.symbol, deal.provider, deal.period // ); } else { result = FindSignalInfoIndex(deal.positionId); } // return result; } // void AddNewSignal( int pusher, XSignal &signal, X121SetupConditions &conditions // ) { // XSignalInfo info; bool isFilled = info.Fill( pusher, signal, conditions // ); // if (isFilled) { // AddRef( info, mSignalInfos // ); } } // void UpdateSignalState(XDeal &deal) { // if (!deal.IsValid()) { return; } // int infoIDX = FindSignalInfoIndex(deal); if (!IsValidIndex(infoIDX)) { return; } // if (deal.entry == DEAL_ENTRY_IN) { // mSignalInfos[infoIDX].time = deal.time; mSignalInfos[infoIDX].ticket = deal.positionId; Print("Open Position: " + ToString(deal.positionId)); } else if (deal.entry == DEAL_ENTRY_OUT) { Print("Close Position: " + ToString(deal.positionId)); } } // double mBullishScore; double mBearishScore; // XSCX121SetupCycles *mSetups[]; // Number of Setups // // Tools ... int CountSetups() { return ArraySize(mSetups); } // int FindSetupIndex( string symbol, ENUM_TIMEFRAMES period // ) { // int result = -1; // int count = CountSetups(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XSCX121SetupCycles *iSetup = mSetups[i]; // X121SetupInputs iInputs = iSetup.GetInputs(); // if (iInputs.symbol == symbol && iInputs.period == period) { // result = i; break; } } // return result; } }; //