/////////////////////////////////////////////////////// // // 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 ... // // Model all Trades Data as this Structure ... struct XTradeInfo { // int pushers; // Signal Pushers datetime time; // Issue Time (Open Position) string symbol; // Trading Symbol double entry; // Entry Price double volume; // Volume string provider; // Signaller ENUM_TIMEFRAMES period; // Trading Timeframe ENUM_X_POSITION_TYPES type; // Position Type // ulong ticket; // Position Ticket double profit; // Profit on Close double commission; // Commission double swap; // Swap string message; // Close Reason datetime endTime; // End Time // X121SetupConditions cConditions; // Generated Current Conditions X121SetupConditions sConditions; // Generated Short Conditions X121SetupConditions mConditions; // Generated Medium Conditions X121SetupConditions lConditions; // Generated Long Conditions X121SetupConditions hConditions; // Generated Hind Conditions // // Constructor ... void XTradeInfo() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // time = NULL; type = NULL; symbol = NULL; period = NULL; endTime = NULL; message = NULL; provider = NULL; // swap = 0; entry = 0; ticket = 0; profit = 0; volume = 0; pushers = 0; commission = 0; // cConditions.Clean(); sConditions.Clean(); mConditions.Clean(); lConditions.Clean(); hConditions.Clean(); // ResetGrid(); ResetSupport(); ResetRecovery(); } // bool Fill( const XSignal &_signal, int _pushers, bool _allowGrid, bool _allowRecover, bool _allowSupport, X121SetupConditions &_cConditions, X121SetupConditions &_sConditions, X121SetupConditions &_mConditions, X121SetupConditions &_lConditions, X121SetupConditions &_hConditions // ) { // bool result = false; // result = // IsValid(_signal.symbol) && IsValid(_signal.period) && IsValid(_signal.provider) // ; // if (!result) { return result; } // pushers = _pushers; time = _signal.time; entry = _signal.entry; symbol = _signal.symbol; period = _signal.period; volume = _signal.volume; provider = _signal.provider; type = ToPositionType(_signal.type); // cConditions = _cConditions; sConditions = _sConditions; mConditions = _mConditions; lConditions = _lConditions; hConditions = _hConditions; // allowGrid = _allowGrid; allowRecover = _allowRecover; allowSupport = _allowSupport; // 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; } // int GetAge() { // int result = -1; // if (!IsValid(symbol) || !IsValid(time) || !IsValid(endTime) || !IsValid(period)) { return result; } // int startIndex = iBarShift( symbol, period, time, false // ); // int endIndex = iBarShift( symbol, period, endTime, false // ); // result = MathAbs(startIndex - endIndex); // return result; } // string GetFileName() { // string result = NULL; // if (!IsValid()) { return result; } // result = // symbol + "\\" + ToString(type) + "\\" + (profit >= 0 ? "Profit" : "Loss") + "\\" + provider + "_" + ToString(ticket) + "_" + ToString(period) + "_" + ToFormatString(time) // ; // return result; } // string ToString() { // string result = NULL; // string cConditionsStr = cConditions .GenerateSummary( false, // Only Commons ... true, // Only Conditions ... false, // Include Score ... false // Include False Conditions ... ); string sConditionsStr = sConditions .GenerateSummary( false, // Only Commons ... true, // Only Conditions ... false, // Include Score ... false // Include False Conditions ... ); string mConditionsStr = mConditions .GenerateSummary( false, // Only Commons ... true, // Only Conditions ... false, // Include Score ... false // Include False Conditions ... ); string lConditionsStr = lConditions .GenerateSummary( false, // Only Commons ... true, // Only Conditions ... false, // Include Score ... false // Include False Conditions ... ); string hConditionsStr = hConditions .GenerateSummary( false, // Only Commons ... true, // Only Conditions ... false, // Include Score ... false // Include False Conditions ... ); // int age = GetAge(); // result = // ToString("Ticket", ticket) + ToString("Symbol", symbol) + ToString("Period", period) + ToString("Entry", entry) + ToString("Provider", provider) + ToString("Type", ToString(type)) + ToString("Time", time) + ToString("Pushers", pushers) + "-------------" + "\n" + ToString("Volume", volume) + ToString("Profit", profit) + ToString("Commission", commission) + ToString("Swap", swap) + ToString("End Time", endTime) + ToString("Age", age) + ToString("Message", message) + "-------------" + "\n" + "Conditions" + "\n" + "-------------" + "\n" + "-------------" + "\n" + "CURRENT [" + ToString(cConditions.period) + "]" + "\n" + "-------------" + "\n" + cConditionsStr + "\n" + "-------------" + "\n" + "SHORT [" + ToString(sConditions.period) + "]" + "\n" + "-------------" + "\n" + sConditionsStr + "\n" + "-------------" + "\n" + "MEDIUM [" + ToString(mConditions.period) + "]" + "\n" + "-------------" + "\n" + mConditionsStr + "\n" + "-------------" + "\n" + "LONG [" + ToString(lConditions.period) + "]" + "\n" + "-------------" + "\n" + lConditionsStr + "\n" + "-------------" + "\n" + "HIND [" + ToString(hConditions.period) + "]" + "\n" + "-------------" + "\n" + hConditionsStr + "\n" + // "" // ; // return result; } // // These are Some Helpers for Trading Controls and do not relate to Main // purpose of Trade Handler ... // // Supporting ... // bool allowSupport; // Allow Support // void ResetSupport() { allowSupport = false; } // // Retrieve Support Signal ... bool HasSupport( XSignal &support // ) { // bool result = false; // return result; } // // Grid System Calculations ... // int gLevel; // Number of Grids bool allowGrid; // Allow Grid double gEntry; // Represents Next Grid Signal's Entry double gVolume; // Represent Next Grid Signal's Volume // void ResetGrid() { // gEntry = 0; gLevel = 0; gVolume = 0; // allowGrid = false; } // void SetGrid( double nextEntry, double nextVolume // ) { // gEntry = nextEntry; gVolume = nextVolume; } // // Prepare Data For Next Grid ... void PrepareNextGrid( double distance, double volumeMultiplier // ) { // bool isValid = // IsValid() && entry > 0 && volume > 0 && distance > 0 && volumeMultiplier > 0 // ; bool isLong = IsLong(type); // double distancePrice = PointToPrice( distance, symbol // ); // double selectedEntry = gEntry <= 0 ? entry : gEntry; double selectedVolume = gVolume <= 0 ? volume : gVolume; // double nextEntry = isLong ? selectedEntry - distancePrice : selectedEntry + distancePrice; double nextVolume = selectedVolume * volumeMultiplier; // SetGrid( nextEntry, nextVolume // ); } // // Check if a Grid Signal Exists Prepared and // Provide it ... bool HasGrid( XSignal &signal, // Result Signal double distance, double volumeMultiplier // ) { // bool result = false; // signal.Clean(); // result = IsValid() && distance > 0 && volumeMultiplier > 0; if (!result) { return result; } // bool isLong = IsLong(type); // ENUM_POSITION_TYPE gType = isLong ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; // double cEntry = GetEntry( symbol, gType // ); // result = isLong ? cEntry <= gEntry : cEntry >= gEntry; if (!result) { return result; } // result = signal.Prepare( symbol, provider, period, gType, X_ORDER_MODE_MARKET, cEntry, gVolume, 0, // SL ... 0 // TP ... ); // if (result) { // // set Support Token ... string comment = GenerateSupportTag(ticket); signal.comment = comment; // PrepareNextGrid( distance, volumeMultiplier // ); // gLevel++; } // return result; } // // Recovery Zone System ... // bool allowRecover; // Allow Recover ENUM_POSITION_TYPE rLastRecoveryType; // Last Executed Recovery Signal's Type double rLongEntry; // Represent Next Recovery Long Signal's Entry double rShortEntry; // Represent Next Recovery Short Signal's Entry double rVolume; // Represent Next Recovery Signal's Volume double rZoneUpper; // Zone Recovery Upper Bound double rZoneLower; // Zone Recovery Lower Bound int rLevel; // Number of Recoveries // void ResetRecovery() { // rLevel = 0; rVolume = 0; rLongEntry = 0; rZoneUpper = 0; rZoneLower = 0; rShortEntry = 0; // allowRecover = false; } // void SetRecovery( double nextLongEntry, double nextShortEntry, double zoneUpper, double zoneLower, double nextVolume // ) { // rVolume = nextVolume; rZoneUpper = zoneUpper; rZoneLower = zoneLower; rLongEntry = nextLongEntry; rShortEntry = nextShortEntry; } // void PrepareNextRecovery( double distance, // Define Target Based On Zones double volumeMultiplier, // Volume Multiplier ENUM_POSITION_TYPE lastType // Last Type ) { // bool isValid = // IsValid() && entry > 0 && volume > 0 && distance > 0 && volumeMultiplier > 0 // ; // bool isLong = IsLong(lastType); // double distancePrice = PointToPrice( distance, symbol // ); // double selectedEntry = isLong ? rLongEntry <= 0 ? entry : rLongEntry : rShortEntry <= 0 ? entry : rShortEntry; double selectedVolume = rVolume <= 0 ? volume : rVolume; // double nextLongEntry = isLong ? selectedEntry : selectedEntry + distancePrice; double nextShortEntry = isLong ? selectedEntry - distancePrice : selectedEntry; // double nextVolume = selectedVolume * volumeMultiplier; // rLevel % 2 == 1 // ? volume // : volume * volumeMultiplier; // double zoneUpper = rZoneUpper > 0 ? rZoneUpper : isLong ? entry + distancePrice : entry + (distancePrice * 2); double zoneLower = rZoneLower > 0 ? rZoneLower : isLong ? entry + (distancePrice * 2) : entry - distancePrice; // SetRecovery( nextLongEntry, nextShortEntry, zoneUpper, zoneLower, nextVolume // ); // rLastRecoveryType = lastType; } // // Check if a Recovery Signal Exists Prepared and // Provide it ... bool HasRecovery( XSignal &signal, // Result Signal ... double distance, double volumeMultiplier // ) { // bool result = false; // signal.Clean(); // result = // IsValid() && entry > 0 && volume > 0 && distance > 0 && volumeMultiplier > 0 // ; if (!result) { return result; } // double distancePrice = PointToPrice( distance, symbol // ); // bool isLong = IsLong(type); bool isLastLong = IsLong(rLastRecoveryType); // // Check For Long Recovery ... double cLongEntry = GetEntry( symbol, POSITION_TYPE_BUY // ); bool hasLongRecovery = !isLastLong && rLongEntry > 0 && cLongEntry >= rLongEntry; // // Check For Short Recovery ... double cShortEntry = GetEntry( symbol, POSITION_TYPE_SELL // ); bool hasShortRecovery = isLastLong && rShortEntry > 0 && cShortEntry <= rShortEntry; // result = hasLongRecovery || hasShortRecovery; if (!result) { return result; } // ENUM_POSITION_TYPE rType = hasLongRecovery ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; // double rEntry = hasLongRecovery ? cLongEntry : cShortEntry; // double rTP = hasLongRecovery ? rZoneUpper : rZoneLower; // double rSL = hasLongRecovery ? rZoneLower : rZoneUpper; // result = signal.Prepare( symbol, provider, period, rType, X_ORDER_MODE_MARKET, rEntry, rVolume, 0, // rSL, // SL ... 0 // rTP // TP ... ); if (result) { // // set Support Token ... string comment = GenerateSupportTag(ticket); signal.comment = comment; // rLevel++; // PrepareNextRecovery( distance, volumeMultiplier, rType // ); } // return result; } }; // // a Class For Read and Write Trade Info Data in Files ... class XTradeInfoCollector { // // Public ... public: // // Props ... // // Constructor(s) ... void XTradeInfoCollector( string _path = NULL // Base Path ) { // mAccount = new XSCAccount(); // if (IsValid(_path)) { mPath = _path; } else { mPath = "XTradeInfo" + "\\" + mAccount.GetCompany(); } } // // Deconstructor ... void ~XTradeInfoCollector() {} // bool IsExists(XTradeInfo &item) { // bool result = false; // int mHandler = GetFileHandlerForRead(item); result = mHandler != INVALID_HANDLE; FileClose(mHandler); // return result; } // bool Save(XTradeInfo &item) { // bool result = false; // // Check info is Valid ... result = item.IsValid(); if (!result) { return result; } // string content = item.ToString(); 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 ... // XSCAccount *mAccount; // string GetFilePath(XTradeInfo &item) { // string fileName = item.GetFileName(); // return GetFilePath(fileName); } string GetFilePath(string fileName) { // string result = ""; // result = // mPath + "\\" + fileName + ".x121.log" // ; // return result; } // int GetFileHandlerForRead(XTradeInfo &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(XTradeInfo &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; } }; // // a Class for Holding all required data for Specified Trade // such as: // - Signal; // - Position; // - Conditions; // - Scores; // - etc ... class XTradeHandler { // public: // // Props ... // // Constructor ... void XTradeHandler( XSCTrade *trade // an Instance of Trader Class ) { // Clean(data); SetSave(false); mTrader = trade; collector = new XTradeInfoCollector(); } // // Getter(s) / Setter(s) ... // // Others ... // bool GetSave() { return mSave; } // void SetSave(bool value) { mSave = value; } // // Trailling Stop ... // bool AllowTrailStop() { return mAllowTrailStop; } // void AllowTrailStop(bool value) { mAllowTrailStop = value; } // bool DisableTrailingWhenOpposit() { return mDisableTrailingWhenOpposit; } // void DisableTrailingWhenOpposit(bool value) { mDisableTrailingWhenOpposit = value; } // double NextTrailPoint() { return mNextTrailPoint; } // void NextTrailPoint(double value) { // if (value < 0) { value = 0; } // mNextTrailPoint = value; } // double FirstTrailPoint() { return mFirstTrailPoint; } // void FirstTrailPoint(double value) { // if (value < 0) { value = 0; } // mFirstTrailPoint = value; } // double NextTrailDistance() { return mNextTrailDistance; } // void NextTrailDistance(double value) { // if (value < 0) { value = 0; } // mNextTrailDistance = value; } // double FirstTrailDistance() { return mFirstTrailDistance; } // void FirstTrailDistance(double value) { // if (value < 0) { value = 0; } // mFirstTrailDistance = value; } // bool EnableTrailling() { // bool result = false; // result = // AllowTrailStop() && NextTrailPoint() > 0 && FirstTrailPoint() > 0 && NextTrailDistance() > 0 && FirstTrailDistance() > 0 // ; // return result; } // // Supporting ... // bool AllowSupport() { return mAllowSupport; } // void AllowSupport(bool value) { mAllowSupport = value; } // bool SupportOnlyForces() { return mSupportOnlyForces; } // void SupportOnlyForces(bool value) { mSupportOnlyForces = value; } // double SupportDistance() { return mSupportDistance; } // void SupportDistance(double value) { // if (value < 0) { value = 0; } // mSupportDistance = value; } // int MaxNumberOfSupports() { return mMaxNumberOfSupports; } // void MaxNumberOfSupports(int value) { // if (value < 0) { value = 0; } // mMaxNumberOfSupports = value; } // double SupportVolumeMultiplier() { return mSupportVolumeMultiplier; } // void SupportVolumeMultiplier(double value) { // if (value < 1) { value = 1; } // mSupportVolumeMultiplier = value; } // double MaxAllowedSupportVolume() { return mMaxAllowedSupportVolume; } // void MaxAllowedSupportVolume(double value) { // if (value < 0.01) { value = 0.01; } // mMaxAllowedSupportVolume = value; } // bool EnableSupport() { // bool result = false; // result = // AllowSupport() && SupportDistance() > 0 && MaxNumberOfSupports() >= 0 && SupportVolumeMultiplier() > 0 // ; // return result; } // // Grid ... // bool AllowGrid() { return mAllowGrid; } // void AllowGrid(bool value) { mAllowGrid = value; } // bool GridOnlyForces() { return mGridOnlyForces; } // void GridOnlyForces(bool value) { mGridOnlyForces = value; } // int MaxNumberOfGrids() { return mMaxNumberOfGrids; } // void MaxNumberOfGrids(int value) { // if (value < 0) { value = 0; } // mMaxNumberOfGrids = value; } // double GridDistance() { return mGridDistance; } // void GridDistance(double value) { // if (value < 0) { value = 0; } // mGridDistance = value; } // double GridVolumeMultiplier() { return mGridVolumeMultiplier; } // void GridVolumeMultiplier(double value) { // if (value < 1) { value = 1; } // mGridVolumeMultiplier = value; } // double MaxAllowedGridVolume() { return mMaxAllowedGridVolume; } // void MaxAllowedGridVolume(double value) { // if (value < 0.01) { value = 0.01; } // mMaxAllowedGridVolume = value; } // // Check Grid Properties to Validate it's Enable or not ... bool EnableGrid() { // bool result = false; // result = // AllowGrid() && GridDistance() > 0 && MaxNumberOfGrids() >= 0 && GridVolumeMultiplier() > 0 // ; // return result; } // // Recovery System ... // bool AllowRecovery() { return mAllowRecovery; } // void AllowRecovery(bool value) { mAllowRecovery = value; } // bool RecoverOnlyForces() { return mRecoverOnlyForces; } // void RecoverOnlyForces(bool value) { mRecoverOnlyForces = value; } // int MaxNumberOfRecoveries() { return mMaxNumberOfRecoveries; } // void MaxNumberOfRecoveries(int value) { // if (value < 0) { value = 0; } // mMaxNumberOfRecoveries = value; } // double RecoveryDistance() { return mRecoveryDistance; } // void RecoveryDistance(double value) { // if (value < 0) { value = 0; } // mRecoveryDistance = value; } // double RecoveryVolumeMultiplier() { return mRecoveryVolumeMultiplier; } // void RecoveryVolumeMultiplier(double value) { // if (value < 1) { value = 1; } // mRecoveryVolumeMultiplier = value; } // double MaxAllowedRecoveryVolume() { return mMaxAllowedRecoveryVolume; } // void MaxAllowedRecoveryVolume(double value) { // if (value < 0.01) { value = 0.01; } // mMaxAllowedRecoveryVolume = value; } // // Check Recovery Properties to Validate it's Enable or not ... bool EnableRecovery() { // bool result = false; // result = // AllowRecovery() && RecoveryDistance() > 0 && MaxNumberOfRecoveries() >= 0 && RecoveryVolumeMultiplier() > 0 // ; // return result; } // // Tools ... // int Count() { return ArraySize(data); } // int FindIndex(ulong ticket) { // int result = -1; // int count = Count(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XTradeInfo iInfo = data[i]; // bool isOwn = iInfo.IsOwn( ticket // ); if (isOwn) { // result = i; break; } } // return result; } // int FindIndex(XSignal &signal) { // int result = -1; // int count = Count(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XTradeInfo iInfo = data[i]; // bool isOWN = // iInfo.time == signal.time && iInfo.symbol == signal.symbol && iInfo.volume == signal.volume && iInfo.period == signal.period && iInfo.provider == signal.provider && iInfo.type == ToPositionType(signal.type) // ; // if (isOWN) { // result = i; break; } } // return result; } // void Add( XSignal &signal, int pushers, bool allowGrid, bool allowRecover, bool allowSupport, X121SetupConditions &cConditions, X121SetupConditions &sConditions, X121SetupConditions &mConditions, X121SetupConditions &lConditions, X121SetupConditions &hConditions // ) { // XTradeInfo info; bool isFilled = info.Fill( signal, pushers, allowGrid, allowRecover, allowSupport, cConditions, sConditions, mConditions, lConditions, hConditions // ); if (!isFilled) { return; } // AddRef( info, data // ); } // void Remove(XSignal &signal) { // int infoIDX = FindIndex(signal); if (!IsValidIndex(infoIDX)) { return; } // ArrayRemove( data, infoIDX, 1 // ); } // void Update(XSignal &signal) { // if (!signal.IsValid() || !signal.IsExecuted()) { return; } // int infoIDX = FindIndex(signal); if (!IsValidIndex(infoIDX)) { return; } // data[infoIDX].ticket = signal.positionId; // // Find Orders for Accessing Commission ... XDeal deals[]; int dealsCount = mTrader.GetDeals( deals, signal.symbol, signal.provider, signal.period, NULL, DEAL_ENTRY_IN // Position Open Deal ... ); if (!IsValidSize(dealsCount)) { return; } // for (int i = 0; i < dealsCount; i++) { // XDeal iDeal = deals[i]; // if (iDeal.positionId == signal.positionId) { data[infoIDX].commission = iDeal.commission; } } // // Check if Grid System Enable or Not ... if (EnableGrid()) { // // Here we Prepare Handler Structure for // Next Grid Position ... data[infoIDX].PrepareNextGrid( GridDistance(), GridVolumeMultiplier() // ); } // // Check if Recovery System Enable or Not ... if (EnableRecovery()) { // data[infoIDX].PrepareNextRecovery( GridDistance(), GridVolumeMultiplier(), signal.type // ); } } // void Update(XDeal &deal) { // if (!deal.IsValid()) { return; } // int infoIDX = FindIndex(deal.positionId); if (!IsValidIndex(infoIDX)) { return; } // data[infoIDX].swap = deal.swap; data[infoIDX].endTime = deal.time; data[infoIDX].profit = deal.profit; // string message = deal.reason == DEAL_REASON_TP ? "TP" : "SL"; data[infoIDX].message = message; // Finish(infoIDX); } // void Update(XPosition &position) { // if (!position.IsValid()) { return; } // int infoIDX = FindIndex(position.ticket); if (!IsValidIndex(infoIDX)) { return; } // data[infoIDX].swap = position.swap; data[infoIDX].endTime = TimeCurrent(); data[infoIDX].profit = position.profit; data[infoIDX].message = position.comment; // Finish(infoIDX); } // // Sync ... void Sync() { // int count = Count(); if (!IsValidSize(count)) { return; } // int mustRemoved[]; for (int i = 0; i < count; i++) { // XTradeInfo iInfo = data[i]; // if (iInfo.ticket > 0 && !mTrader.IsOpen(iInfo.ticket)) { // AddSpecific( i, mustRemoved // ); } } // int mustRemovedCount = ArraySize(mustRemoved); if (!IsValidSize(mustRemovedCount)) { return; } // for (int i = 0; i < mustRemovedCount; i++) { // ArrayRemove( data, i, 1 // ); } } // // Protection Handlers ... // // Handle Do All Protecting ... int DoProtect( XSignal &signals[], // if PRotecting Generate Some Support Signals, Holds them here XSCX121SetupCycles *&setups[] // Number of Setups ) { // int result = 0; // // Calling Protection Algorithms ... // // Trailling ... if (EnableTrailling()) { int traillings = HandleTrailling(); } // if (AllowSupport()) { // XSignal supports[]; int supportsCount = RequestForSupport( supports, setups // ); // if (IsValidSize(supportsCount)) { // Copy( supports, signals, false // ); } } // // Grid ... if (EnableGrid()) { // XSignal grids[]; int gridsCount = RequestForGrid(grids); if (IsValidSize(gridsCount)) { // Copy( grids, signals, false // ); } } // // Recovery ... if (EnableRecovery()) { // XSignal recoveries[]; int recoveriesCount = RequestForRecovery(recoveries); if (IsValidSize(recoveriesCount)) { // Copy( recoveries, signals, false // ); } } // result = ArraySize(signals); // return result; } // int GetBreakoutsSignals(XSignal &signals[]) { // int result = 0; // Clean(signals); // int count = Count(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // double iEntry = data[i].entry; string iSymbol = data[i].symbol; ENUM_TIMEFRAMES iPeriod = data[i].period; ENUM_X_POSITION_TYPES iType = data[i].type; // bool isLong = IsLong(iType); ENUM_POSITION_TYPE iPType = isLong ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; // double cEntry = GetEntry( iSymbol, iPType // ); // XOHCL cBar; bool isInited = cBar.Init( iSymbol, iPeriod, 1 // ); if (!isInited) { continue; } // bool isBullish = cBar.IsBullish(); bool isBreakUp = cBar.IsBreakUp(iEntry); // bool isBearish = cBar.IsBearish(); bool isBreakDown = cBar.IsBreakDown(iEntry); // bool isBreaked = isLong ? isBullish && isBreakUp && cEntry > iEntry : isBearish && isBreakDown && cEntry < iEntry; // if (isBreaked) { // // Update Date of TradeInfo ... data[i].entry = cEntry; data[i].time = TimeCurrent(); // // Generate Signal ... XSignal iSignal; bool isPrepared = iSignal.Prepare( data[i].symbol, data[i].provider, data[i].period, iPType, X_ORDER_MODE_MARKET, data[i].entry, data[i].volume, 0, 0 // ); // // Add Signal to Result ... if (isPrepared) { // AddRef( iSignal, signals // ); } } // // // double hotLevels[]; // // // AddSpecific( // 0.25, // hotLevels // // ); // // // AddSpecific( // 0.20, // hotLevels // // ); // // // AddSpecific( // 0.12, // hotLevels // // ); // // // XSCZonesInput zonesInput; // zonesInput.length = 71; // zonesInput.numberOfZones = 10; // XSCZones *zones = new XSCZones( // iSymbol, // _Period // // ); // // // zonesInput.AddLevelColor( // hotLevels[0], // clrRed // // ); // zonesInput.AddLevelColor( // hotLevels[1], // clrOrange // // ); // zonesInput.AddLevelColor( // hotLevels[2], // clrLightCoral // // ); // bool canUseZones = zones.Init(zonesInput); // // // XSCCFInput cfInputs; // cfInputs.Default(); // XSCCF *cf = new XSCCF( // iSymbol, // _Period // // ); // bool canUseCF = cf.Init(cfInputs); // // // XSCTrendInput tInputs; // tInputs.Default(); // XSCTrend *trend = new XSCTrend( // iSymbol, // _Period // // ); // bool canUseTrend = trend.Init(tInputs); // if (canUseCF && canUseTrend && canUseZones) // { // // // // cf.Draw(); // trend.Draw(); // // zones.Draw(); // Print("Use CF ..."); // // cf.Remove(); // // trend.Remove(); // // zones.Remove(); // } } // result = ArraySize(signals); // return result; } // // Protected ... protected: // // Props ... XSCTrade *mTrader; XTradeInfo data[]; XTradeInfoCollector *collector; // bool mSave; // Save Results ... // // Trailling ... bool mAllowTrailStop; // Enable Trailling Stop Losses bool mDisableTrailingWhenOpposit; // Disable Trailling When has Opposite In Drawdown double mNextTrailPoint; // Next Trailling Step double mFirstTrailPoint; // First Stop Trail double mFirstTrailDistance; // Start Trailling Distance double mNextTrailDistance; // Next Trailling Distance // // Supporting ... bool mAllowSupport; // Allow Support Signals bool mSupportOnlyForces; // Support Only Force Signals double mSupportDistance; // Supporting Distance int mMaxNumberOfSupports; // Max Number of Support Signals double mSupportVolumeMultiplier; // Support Signals Volume Multiplier double mMaxAllowedSupportVolume; // Max Allowed Support Signals Volume // // Grid ... bool mAllowGrid; // Allow Grid Signals bool mGridOnlyForces; // Grid Only Force Signals int mMaxNumberOfGrids; // Max Number of Grid Signals double mGridDistance; // Grid Distance double mGridVolumeMultiplier; // Grid Volume Multiplier double mMaxAllowedGridVolume; // Max Allowed Grid Signals Volume // // Recovery ... bool mAllowRecovery; // Allow Recovery Signals bool mRecoverOnlyForces; // Recover Only Force Signals int mMaxNumberOfRecoveries; // Max Number of Recovery Signals double mRecoveryDistance; // Recovery Distance double mRecoveryVolumeMultiplier; // Recovery Volume Multiplier double mMaxAllowedRecoveryVolume; // Max Allowed Recovery Signals Volume // // Tools ... // void Finish(int index) { // XTradeInfo info = data[index]; if (!info.IsValid()) { return; } // ArrayRemove( data, index, 1 // ); // if (GetSave()) { collector.Save(info); } } // // Protection Methods ... // int HandleTrailling() { // int result = 0; // // Check Trailling is Enabled or not ... if (!EnableTrailling()) { return result; } // // Do Synch Before Start Trailing ... Sync(); // // Since Trailing Done based On In Profit Positions ... // First we Check if ... XPosition positions[]; XPosition inDPositions[]; XPosition inPPositions[]; int positionsCount = mTrader.GetPositions(positions); if (!IsValidSize(positionsCount)) { return result; } // int inDPositionsCount = ExtractInDrawdownPositions( positions, inDPositions // ); int inPPositionsCount = ExtractInProfitPositions( positions, inPPositions // ); if (!IsValidSize(inPPositionsCount)) { return result; } // for (int i = 0; i < inPPositionsCount; i++) { // XPosition iPosition = inPPositions[i]; // // ignore Support Positions ... bool isSupport = IsSupport(iPosition.comment); if (isSupport) { continue; } // // Only Trail Positions which they Hasnt any Support ... bool hasSupport = mTrader.HasSupport(iPosition.ticket); result = !hasSupport; if (!result) { return result; } // // Find Positin Info Index ... int idx = FindIndex(iPosition.ticket); if (!IsValidIndex(idx)) { continue; } // bool isLong = IsLong(iPosition.type); // // Here we Select Price for SL Trailling ... double usedPrice = 0; if (iPosition.sl != 0) { // if (isLong) { // if (iPosition.sl < iPosition.entry) { usedPrice = iPosition.entry; } else { usedPrice = iPosition.sl; } } else { // if (iPosition.sl > iPosition.entry) { usedPrice = iPosition.entry; } else { usedPrice = iPosition.sl; } } } else { usedPrice = iPosition.entry; } // double nextTrailPoint = NextTrailPoint(); double firstTrailPoint = FirstTrailPoint(); double nextTrailDistance = NextTrailDistance(); double firstTrailDistance = FirstTrailDistance(); // bool isFirstTrail = usedPrice == iPosition.entry; // double usedTrailDiff = isFirstTrail ? MathMax(firstTrailPoint, firstTrailDistance) : MathMax(nextTrailPoint, nextTrailDistance); // double iExit = GetExit( iPosition.symbol, iPosition.type // ); double iPriceDistance = MathAbs(usedPrice - iExit); double iPriceDistanceInPoint = PriceToPoint( iPriceDistance, iPosition.symbol // ); // bool canTrail = iPriceDistanceInPoint >= usedTrailDiff; if (!canTrail) { continue; } // // Check Opposit Side Position ... // if Exists, dont Trail ... if (DisableTrailingWhenOpposit() && IsValidSize(inDPositionsCount)) { // bool canTrail = true; ENUM_POSITION_TYPE oppositType = GetOpposit(iPosition.type); for (int j = 0; j < inDPositionsCount; j++) { // XPosition inDPosition = inDPositions[j]; // bool isOpposit = inDPosition.symbol == iPosition.symbol && inDPosition.type == oppositType; if (isOpposit) { // canTrail = false; break; } } // if (!canTrail) { continue; } } // usedTrailDiff = isFirstTrail ? MathMin(firstTrailPoint, firstTrailDistance) : MathMin(nextTrailPoint, nextTrailDistance); double usedTrailDiffPrice = PointToPrice( usedTrailDiff, iPosition.symbol // ); // double sl = isLong ? usedPrice + usedTrailDiffPrice : usedPrice - usedTrailDiffPrice; string comment = PrepareSLTrailTag(iPosition.comment); // bool isModified = mTrader.Modify( iPosition.ticket, sl, iPosition.tp, comment // ); if (isModified) { result++; } } // return result; } // int RequestForSupport( XSignal &signals[], XSCX121SetupCycles *&setups[] // ) { // int result = 0; // Clean(signals); // if (!AllowSupport()) { return result; } // Sync(); // int count = Count(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XSignal iSupport; double iPivot = -1; int iPivotIDX = -1; bool hasSupport = data[i].HasSupport( iSupport // ); if (hasSupport) { // AddRef( iSupport, signals // ); } } // result = ArraySize(signals); // // TODO: Complete this Later ... return result; // // Validate Setups Count ... // int setupsCount = ArraySize(setups); // if (!IsValidSize(setupsCount)) // { // return result; // } // // // // Implement Supporting Mechanism ... // // // // Extracting In Drawdown Positions ... // XPosition positions[]; // int positionsCount = mTrader.GetInDrawdownPositions( // positions // // ); // if (!IsValidSize(positionsCount)) // { // return result; // } // // // double supportDistance = SupportDistance(); // int maxNUmberOfSupports = MaxNumberOfSupports(); // double maxAllowedVolume = MaxAllowedSupportVolume(); // double volumeMultiplier = SupportVolumeMultiplier(); // // // X121SignalGenerator signalGenerator; // // // for (int i = 0; i < positionsCount; i++) // { // // // XPosition iPosition = positions[i]; // // // // Check Position is not Support Position ... // bool isSupport = IsSupport(iPosition.comment); // if (isSupport) // { // continue; // } // // // // Find Related Setp ... // int idx = FindSetupIndex( // iPosition.symbol, // setups // // ); // if (!IsValidIndex(idx)) // { // continue; // } // // // int index = FindIndex(iPosition.ticket); // if (!IsValidIndex(index)) // { // continue; // } // // // // Check Position must atleast 20 Point in drawdown ... // // // double onePointPrice = PointToPrice( // 1, // iPosition.symbol // // ); // // // double iExitPrice = GetExit( // iPosition.symbol, // iPosition.type // // ); // // // double priceDiff = MathAbs(iPosition.entry - iExitPrice); // double priceDiffPoints = priceDiff / onePointPrice; // // // bool isFarEnough = priceDiffPoints >= (supportDistance / 2); // if (!isFarEnough) // { // continue; // } // // // // Check Support COunts and etc ... // // implementing supporting mechanis ... // // // } // // // result = ArraySize(signals); // return result; } // int RequestForGrid(XSignal &signals[]) { // int result = 0; // Clean(signals); // if (!EnableGrid()) { return result; } // int maxAllowed = MaxNumberOfGrids(); double maxAllowedVolume = MaxAllowedGridVolume(); // int count = Count(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // // Check Count ... bool isMaxPassed = maxAllowed <= 0 ? true : data[i].gLevel < maxAllowed; if (!isMaxPassed) { continue; } // XSignal iSignal; bool hasGrid = data[i].HasGrid( iSignal, GridDistance(), GridVolumeMultiplier() // ); // if (hasGrid) { // // Check Max Volume ... iSignal.volume = maxAllowedVolume <= 0 ? iSignal.volume : MathMin(iSignal.volume, maxAllowedVolume); // AddRef( iSignal, signals // ); } } // result = ArraySize(signals); // return result; } // int RequestForRecovery(XSignal &signals[]) { // int result = 0; // Clean(signals); // if (!EnableRecovery()) { return result; } // int maxAllowed = MaxNumberOfRecoveries(); double maxAllowedVolume = MaxAllowedRecoveryVolume(); // int count = Count(); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // // Check Count ... bool isMaxPassed = maxAllowed <= 0 ? true : data[i].rLevel < maxAllowed; if (!isMaxPassed) { continue; } // XSignal iSignal; bool hasRecovery = data[i].HasRecovery( iSignal, RecoveryDistance(), RecoveryVolumeMultiplier() // ); // if (hasRecovery) { // // Check Max Volume ... iSignal.volume = maxAllowedVolume <= 0 ? iSignal.volume : MathMin(iSignal.volume, maxAllowedVolume); // AddRef( iSignal, signals // ); } } // result = ArraySize(signals); // return result; } // int FindSetupIndex( string symbol, XSCX121SetupCycles *&setups[] // ) { // int result = 0; // if (!IsValid(symbol)) { return result; } // for (int i = 0; i < ArraySize(setups); i++) { // if (setups[i].GetSymbol() == symbol) { // result = i; break; } } // return result; } // void AddHotLevelsToZones( XSCZones *zones // ) { // zones.AddLevelColor( 0.25, clrRed // ); zones.AddLevelColor( 0.20, clrOrange // ); zones.AddLevelColor( 0.15, clrYellow // ); } }; // // Class ... class XSCX121SetupEA : public XSCBaseEA { // // Public ... public: // // Props ... X121SignalGenerator signalGenerator; // // Constructors ... XSCX121SetupEA( // // XTrade Class Requirements ... int slippage, // Specify Slippage ulong magicNumber, // Specify Magic Number // // XSCTrade Event Handlers ... TOnSignal onSignal = NULL, // On Signal Recieved Event Handler TOnModify onModifyPosition = NULL, // On Modify Position Event Handler TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler TOnForceClose onForceClosePosition = NULL, // On Force Close Position Event Handler TOnPartialClose onPartialClosePosition = NULL, // On Partial Close Position 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, onSignal, onModifyPosition, onStopLossTriggered, onTakeProfitTriggered, onForceClosePosition, onPartialClosePosition, onDealsChangedHandler, onOrdersChangedHandler, onPositionsChangedHandler, onTradeStateChangedHandler // ) { // mTradeHandler = new XTradeHandler(mTrader); // // Implement Default Configs ... DefaultConfigs(); } // // Deconstructor ... ~XSCX121SetupEA() { // delete mTradeHandler; // Clean(mSetups); } // bool AddSetup(XSCX121SetupCycles *setup) { // bool result = false; // result = setup != NULL; if (!result) { return result; } // Add( setup, mSetups // ); // return result; } // // Getter(s) / Setter(s) ... // /// Signals ... // bool AllowLong() { return mAllowLong; } // void AllowLong(bool value) { mAllowLong = value; } // bool AllowShort() { return mAllowShort; } // void AllowShort(bool value) { mAllowShort = value; } // int DelayBetweenTwoSignal() { return mDelayBetweenTwoSignal; } // void DelayBetweenTwoSignal(int value) { // if (value < 0) { value = 0; } // mDelayBetweenTwoSignal = value; } // int ReuiredSignalVerifications() { return mReuiredSignalVerifications; } // void ReuiredSignalVerifications(int value) { // if (value < 1) { value = 1; } // mReuiredSignalVerifications = value; } // bool GetVerificationFromOtherTimeFrames() { return mGetVerificationFromOtherTimeFrames; } // void GetVerificationFromOtherTimeFrames(bool value) { mGetVerificationFromOtherTimeFrames = value; } // bool ExecuteSignalsOnBreakout() { return mExecuteSignalsOnBreakout; } // void ExecuteSignalsOnBreakout(bool value) { mExecuteSignalsOnBreakout = value; } // // Risk Management ... // double Volume() { return mVolume; } // void Volume(double value) { // if (value < 0.01) { value = 0.01; } // mVolume = 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; } // int MaxAllowedTrades() { return mMaxAllowedTrades; } // void MaxAllowedTrades(int value) { // if (value < 0) { value = 0; } // mMaxAllowedTrades = value; // mTrader.SetMaxAllowedPositions(value); } // bool UseMaxAllowedPerDirection() { return mUseMaxAllowedPerDirection; } // void UseMaxAllowedPerDirection(bool value) { mUseMaxAllowedPerDirection = value; } // bool IgnoreTP() { return mIgnoreTP; } // void IgnoreTP(bool value) { mIgnoreTP = value; } // bool IgnoreSL() { return mIgnoreSL; } // void IgnoreSL(bool value) { mIgnoreSL = value; } // // Signalling ... // int StartSignallingHoure() { return mStartSignallingHoure; } // void StartSignallingHoure(int value) { // if (value < -1) { value = -1; } // mStartSignallingHoure = value; } // int EndSignallingHoure() { return mEndSignallingHoure; } // void EndSignallingHoure(int value) { // if (value < -1) { value = -1; } // mEndSignallingHoure = value; } // int CloseOnSpecificTime() { return mCloseOnSpecificTime; } // void CloseOnSpecificTime(int value) { // if (value < -1) { value = -1; } // mCloseOnSpecificTime = value; } // bool CloseOnOpposit() { return mCloseOnOpposit; } // void CloseOnOpposit(bool value) { mCloseOnOpposit = value; } // // Trailling ... // bool AllowTrailStop() { return mTradeHandler.AllowTrailStop(); } // void AllowTrailStop(bool value) { mTradeHandler.AllowTrailStop(value); } // bool DisableTrailingWhenOpposit() { return mTradeHandler.DisableTrailingWhenOpposit(); } // void DisableTrailingWhenOpposit(bool value) { mTradeHandler.DisableTrailingWhenOpposit(value); } // double NextTrailPoint() { return mTradeHandler.NextTrailPoint(); } // void NextTrailPoint(double value) { mTradeHandler.NextTrailPoint(value); } // double FirstTrailPoint() { return mTradeHandler.FirstTrailPoint(); } // void FirstTrailPoint(double value) { mTradeHandler.FirstTrailPoint(value); } // double NextTrailDistance() { return mTradeHandler.NextTrailDistance(); } // void NextTrailDistance(double value) { mTradeHandler.NextTrailDistance(value); } // double FirstTrailDistance() { return mTradeHandler.FirstTrailDistance(); } // void FirstTrailDistance(double value) { mTradeHandler.FirstTrailDistance(value); } // // Supporting ... // bool AllowSupport() { return mTradeHandler.AllowSupport(); } // void AllowSupport(bool value) { mTradeHandler.AllowSupport(value); } // bool SupportOnlyForces() { return mTradeHandler.SupportOnlyForces(); } // void SupportOnlyForces(bool value) { mTradeHandler.SupportOnlyForces(value); } // bool EnableSupport() { return mTradeHandler.EnableSupport(); } // double SupportDistance() { return mTradeHandler.SupportDistance(); } // void SupportDistance(double value) { mTradeHandler.SupportDistance(value); } // int MaxNumberOfSupports() { return mTradeHandler.MaxNumberOfSupports(); } // void MaxNumberOfSupports(int value) { mTradeHandler.MaxNumberOfSupports(value); } // double SupportVolumeMultiplier() { return mTradeHandler.SupportVolumeMultiplier(); } // void SupportVolumeMultiplier(double value) { mTradeHandler.SupportVolumeMultiplier(value); } // double MaxAllowedSupportVolume() { return mTradeHandler.MaxAllowedSupportVolume(); } // void MaxAllowedSupportVolume(double value) { mTradeHandler.MaxAllowedSupportVolume(value); } // // Grid ... // bool AllowGrid() { return mTradeHandler.AllowGrid(); } // void AllowGrid(bool value) { mTradeHandler.AllowGrid(value); } // bool GridOnlyForces() { return mTradeHandler.GridOnlyForces(); } // void GridOnlyForces(bool value) { mTradeHandler.GridOnlyForces(value); } // bool EnableGrid() { return mTradeHandler.EnableGrid(); } // int MaxNumberOfGrids() { return mTradeHandler.MaxNumberOfGrids(); } // void MaxNumberOfGrids(int value) { mTradeHandler.MaxNumberOfGrids(value); } // double GridDistance() { return mTradeHandler.GridDistance(); } // void GridDistance(double value) { mTradeHandler.GridDistance(value); } // double GridVolumeMultiplier() { return mTradeHandler.GridVolumeMultiplier(); } // void GridVolumeMultiplier(double value) { mTradeHandler.GridVolumeMultiplier(value); } // double MaxAllowedGridVolume() { return mTradeHandler.MaxAllowedGridVolume(); } // void MaxAllowedGridVolume(double value) { mTradeHandler.MaxAllowedGridVolume(value); } // // Recovery System ... // bool AllowRecovery() { return mTradeHandler.AllowRecovery(); } // void AllowRecovery(bool value) { mTradeHandler.AllowRecovery(value); } // bool RecoverOnlyForces() { return mTradeHandler.RecoverOnlyForces(); } // void RecoverOnlyForces(bool value) { mTradeHandler.RecoverOnlyForces(value); } // bool EnableRecovery() { return mTradeHandler.EnableRecovery(); } // int MaxNumberOfRecoveries() { return mTradeHandler.MaxNumberOfRecoveries(); } // void MaxNumberOfRecoveries(int value) { mTradeHandler.MaxNumberOfRecoveries(value); } // double RecoveryDistance() { return mTradeHandler.RecoveryDistance(); } // void RecoveryDistance(double value) { mTradeHandler.RecoveryDistance(value); } // double RecoveryVolumeMultiplier() { return mTradeHandler.RecoveryVolumeMultiplier(); } // void RecoveryVolumeMultiplier(double value) { mTradeHandler.RecoveryVolumeMultiplier(value); } // double MaxAllowedRecoveryVolume() { return mTradeHandler.MaxAllowedRecoveryVolume(); } // void MaxAllowedRecoveryVolume(double value) { mTradeHandler.MaxAllowedRecoveryVolume(value); } // // Others ... // bool SaveResults() { return mTradeHandler.GetSave(); } // void SaveResults(bool value) { mTradeHandler.SetSave(value); } // double MinFreeMargingForHandleForce() { return mMinFreeMargingForHandleForce; } // void MinFreeMargingForHandleForce(double value) { // if (value < 0) { value = 0; } // mMinFreeMargingForHandleForce = value; } // // Overrides ... // // Customize Token ... string GetToken() override { return GetSpecificToken(this); } // string GetTag() override { return this.GetToken(); } // // Tools ... // // 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; } // // Current ... XSignal cSignal; int cPusher = 0; bool cHasSignal = false; string cProvider = NULL; X121SetupConditions cConditions; // // Short ... XSignal sSignal; int sPusher = 0; bool sHasSignal = false; string sProvider = NULL; X121SetupConditions sConditions; // // Medium ... XSignal mSignal; int mPusher = 0; bool mHasSignal = false; string mProvider = NULL; X121SetupConditions mConditions; // // Long ... XSignal lSignal; int lPusher = 0; bool lHasSignal = false; string lProvider = NULL; X121SetupConditions lConditions; // // Hind ... XSignal hSignal; int hPusher = 0; bool hHasSignal = false; string hProvider = NULL; X121SetupConditions hConditions; // bool canSupport = // EnableSupport() && !SupportOnlyForces() // ; bool canGrid = // EnableGrid() && !GridOnlyForces() // ; bool canRecover = // EnableRecovery() && !RecoverOnlyForces() // ; // double volume = Volume(); double slPoint = SLPoint(); double tpPoint = TPPoint(); bool ignoreSL = IgnoreSL(); bool ignoreTP = IgnoreTP(); bool allowLong = AllowLong(); bool allowShort = AllowShort(); // bool useCMarket = true; bool useSMarket = false; bool useMMarket = false; bool useLMarket = false; bool useHMarket = false; // for (int i = 0; i < count; i++) { // // Current Market ... // cPusher = 0; cSignal.Clean(); cProvider = NULL; cHasSignal = false; cConditions.Clean(); // cHasSignal = !useCMarket ? false : mSetups[i] .ProcessMarket( cSignal, cConditions, cPusher, cProvider, X_MARKET_CYCLE_UNKNOWN, canSupport, allowLong, allowShort, volume, slPoint, ignoreSL, tpPoint, ignoreTP, 0, 5 // ); // // Short Market ... // sPusher = 0; sSignal.Clean(); sProvider = NULL; sHasSignal = false; sConditions.Clean(); // sHasSignal = !useSMarket ? false : mSetups[i] .ProcessMarket( sSignal, sConditions, sPusher, sProvider, X_MARKET_CYCLE_SHORT, canSupport, allowLong, allowShort, volume, slPoint, ignoreSL, tpPoint, ignoreTP, 0, 5 // ); // // Medium Market ... // mPusher = 0; mSignal.Clean(); mProvider = NULL; mHasSignal = false; mConditions.Clean(); // mHasSignal = !useMMarket ? false : mSetups[i] .ProcessMarket( mSignal, mConditions, mPusher, mProvider, X_MARKET_CYCLE_MEDIUM, canSupport, allowLong, allowShort, volume, slPoint, ignoreSL, tpPoint, ignoreTP, 0, 5 // ); // // Long Market ... // lPusher = 0; lSignal.Clean(); lProvider = NULL; lHasSignal = false; lConditions.Clean(); // lHasSignal = !useLMarket ? false : mSetups[i] .ProcessMarket( lSignal, lConditions, lPusher, lProvider, X_MARKET_CYCLE_LONG, canSupport, allowLong, allowShort, volume, slPoint, ignoreSL, tpPoint, ignoreTP, 0, 5 // ); // // Hind Market ... // hPusher = 0; hSignal.Clean(); hProvider = NULL; hHasSignal = false; hConditions.Clean(); // hHasSignal = !useHMarket ? false : mSetups[i] .ProcessMarket( hSignal, hConditions, hPusher, hProvider, X_MARKET_CYCLE_HIND, canSupport, allowLong, allowShort, volume, slPoint, ignoreSL, tpPoint, ignoreTP, 0, 5 // ); // // Parse Signals and Add them for Executing ... // // Check if there is a Signal or Not ... bool hasSignal = cHasSignal || sHasSignal || mHasSignal || lHasSignal || hHasSignal; if (hasSignal) { // XSignal signal; X121SetupConditions otherConditions[]; // if (cHasSignal) { // signal = cSignal; // AddRef( sConditions, otherConditions // ); AddRef( mConditions, otherConditions // ); // AddRef( // lConditions, // otherConditions // // ); // AddRef( // hConditions, // otherConditions // // ); } // if (sHasSignal) { // signal = sSignal; // AddRef( cConditions, otherConditions // ); AddRef( mConditions, otherConditions // ); // AddRef( // lConditions, // otherConditions // // ); // AddRef( // hConditions, // otherConditions // // ); } // if (mHasSignal) { // signal = mSignal; // AddRef( sConditions, otherConditions // ); AddRef( lConditions, otherConditions // ); } // if (lHasSignal) { // signal = lSignal; // // AddRef( // cConditions, // otherConditions // // ); AddRef( mConditions, otherConditions // ); AddRef( hConditions, otherConditions // ); } // if (hHasSignal) { // signal = hSignal; // AddRef( cConditions, otherConditions // ); AddRef( sConditions, otherConditions // ); AddRef( mConditions, otherConditions // ); AddRef( lConditions, otherConditions // ); AddRef( hConditions, otherConditions // ); } // int pushers = cPusher + sPusher + mPusher + lPusher + hPusher; // bool isLong = IsLong(signal.type); // // Validate Signal ... bool isValid = // // Handle Pusher Validations ... (mReuiredSignalVerifications <= 0 ? true : pushers >= mReuiredSignalVerifications) // && // // Handle Other Conditions Validations ... (!mGetVerificationFromOtherTimeFrames ? true : isLong ? signalGenerator.HasLongVerifications(otherConditions) : signalGenerator.HasShortVerifications(otherConditions)) // ; // bool forceState = mSetups[i].ForceState(); // if (!forceState) { // // Add Signal to Execution Result ... AddRef( signal, signals // ); // // Add new Signal Info ... mTradeHandler.Add( signal, pushers, canGrid, canRecover, canSupport, cConditions, sConditions, mConditions, lConditions, hConditions // ); } else { // // Clear Other Conditions ... Clean(otherConditions); // // Fill All Conditions to Other Conditions ... AddRef( cConditions, otherConditions // ); AddRef( sConditions, otherConditions // ); AddRef( mConditions, otherConditions // ); AddRef( lConditions, otherConditions // ); AddRef( hConditions, otherConditions // ); // // If Recieved Any Unverified Signal // we Passed it to EQM Manager ... EQMHandleInvalidSignal( signal, pushers, isValid, otherConditions // ); } } } // 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[]; XSignal eSignals[]; // Must Executed Copy( signals, tmpSignals // ); // Clean(signals); // int maxAllowed = MaxAllowedTrades(); bool perDirection = UseMaxAllowedPerDirection(); // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = tmpSignals[i]; // bool isSignalValid = false; // // Handle Close All Positions when Opposit Signal Recieved ... if (mCloseOnOpposit) { // // Select Signal Opposit Positions ... ENUM_X_POSITION_TYPES iOpposit = GetOppositPositionType(iSignal.type); // XPosition iPositions[]; int iPositionsCount = mTrader.GetPositions( iPositions, iSignal.symbol, NULL, // All Providers ... NULL, // All Periods ... iOpposit // Opposit Positions ... ); // if (IsValidSize(iPositionsCount)) { // string comment = "Close due Opposit ..."; // int closeds = Close( iPositions, comment // ); if (IsValidSize(closeds)) { // string message = XEQMSupportToken + " Closed " + ToString(iPositionsCount) + " due Opposit Signal ..."; // Alert(message); } } } // // TODO: Remove this ... // isSignalValid = !AllowSupport() // ? true // : IsValidSize(ArraySize(iSignal.supports)); // if (!isSignalValid) // { // continue; // } // // Filter Signals Based On Max Allowed ... if (maxAllowed > 0) { // // Here we Get Opposite Signals of Same Symbol Valid ... ENUM_X_POSITION_TYPES iType = perDirection ? ToPositionType(iSignal.type) : X_POSITION_TYPE_ALL; XPosition iSymbolsPositions[]; int iSymbolsPositionsCount = mTrader.GetPositions( iSymbolsPositions, iSignal.symbol, NULL, // Provider NULL, // Period iType, // Type true // ); // int iSupportsCount = 0; if (IsValidSize(iSymbolsPositionsCount)) { // // Filter Support Positions ... XPosition iSupports[]; iSupportsCount = ExtractSupports( iSymbolsPositions, iSupports // ); } // isSignalValid = iSupportsCount <= 0 ? iSymbolsPositionsCount < maxAllowed : iSymbolsPositionsCount - iSupportsCount < maxAllowed; if (!isSignalValid) { continue; } } else { isSignalValid = true; } // if (isSignalValid) { // // Check Delay Between Two Signals ... bool isDelayPassed = IsSignalDelayPassed(iSignal); // if (isDelayPassed) { // AddRef( iSignal, eSignals // ); } } } // // Cutom Signal Execution ... HandleSignals(eSignals); // 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; // // Do all State Management here ... // // Check if there are open Positions // and their doesn't have TP and SL and // Youngest Age of Positions longest as enough // Make State of Signalling to Force State for Recieving // Signal and Clear their Tp and SL for allowing hedges ... EQMHandleForceState(); // DoHedge(); // // Handle Close All Positions on Specific Time ... DoEQMCloseOnSpecificTime(); // // Do EQM Protection if Provided ... DoEQMProtect(); // // if Returns true, Signal Execution failed ... return result; } // // Signal Info ... // void OnSignalExecuted(const XSignal &signal) override { // // Signal Info Manager ... XSignal tSignal = signal; bool isSupport = IsSupport(signal.comment); if (!isSupport) { mTradeHandler.Update(tSignal); } // mTradeHandler.Sync(); } // void OnSignalExecutionFailed( const XSignal &signal, const ENUM_X_SIGNAL_EXECUTION_RESULT reason // ) override { // // Signal Info Manager ... XSignal tSignal = signal; mTradeHandler.Remove(tSignal); mTradeHandler.Sync(); } // void OnPositionClosed( const XPosition &position, const string comment // ) override { // // When a Position Closed Manually ... // Signal Info Manager ... XPosition tPosition = position; bool isSupport = ExtractSupportedTicket(position.comment) > 0; bool isEQMSupport = ExtractEQMSupportedTicket(position.comment) > 0; tPosition.comment = comment; if (!isSupport && !isEQMSupport) { mTradeHandler.Update(tPosition); } // mTradeHandler.Sync(); } // void OnStopLossTriggered(const XDeal &deal) override { // // When a Position's Stop Loss Triggered ... // Signal Info Manager ... XDeal tDeal = deal; mTradeHandler.Update(tDeal); mTradeHandler.Sync(); } // void OnTakeProfitTriggered(const XDeal &deal) override { // // When a Position's Take Profit Triggered ... // Signal Info Manager ... XDeal tDeal = deal; mTradeHandler.Update(tDeal); mTradeHandler.Sync(); } // // Protected ... protected: // // Tools ... // // Check Signalling Enable or not ... bool IsEnable() { // bool result = false; // // Check Signal Type is Enabled or not ... bool isTypePassed = mAllowLong || mAllowShort; // // Check Signalling Time ... MqlDateTime cTime; bool isTimeRecieved = TimeCurrent(cTime); // int endHour = EndSignallingHoure(); int startHour = StartSignallingHoure(); // bool isStartHourPassed = startHour <= -1 ? true : cTime.hour >= startHour; bool isEndHourPassed = endHour <= -1 ? true : cTime.hour < endHour; bool isTimePassed = isTimeRecieved && isStartHourPassed && isEndHourPassed; // result = isTypePassed && isTimePassed; // return result; } // bool CanCloseOnTime() { // bool result = false; // result = mCloseOnSpecificTime >= 0 && mCloseOnSpecificTime <= 23; if (!result) { return result; } // MqlDateTime timeStruct; result = TimeCurrent(timeStruct); if (!result) { return result; } // result = timeStruct.hour == mCloseOnSpecificTime; // return result; } // // Custom Signal Execution ... void HandleSignals(XSignal &signals[]) { // int signalsCount = ArraySize(signals); if (!IsValidSize(signals)) { return; } // bool isMarginPassed = IsMarginPassed(); if (!isMarginPassed) { // string message = "No Margin For Execute Signals ..."; // Alert(message); // return; } // bool isNumberOfPositionsPassed = IsNumberOfPositionsPassed(); if (!isNumberOfPositionsPassed) { // string message = "Max Allowed Signals Reached ..."; // Alert(message); // return; } // bool executeOnBreakouts = ExecuteSignalsOnBreakout(); if (executeOnBreakouts) { // XSignal bSignals[]; int bSignalsCount = mTradeHandler.GetBreakoutsSignals(bSignals); if (IsValidSize(bSignalsCount)) { // ENUM_X_SIGNAL_EXECUTION_RESULT states[]; int executedSignalsCount = ExecuteSignals( signals, states, false // ); } } else { // ENUM_X_SIGNAL_EXECUTION_RESULT states[]; int executedSignalsCount = ExecuteSignals( signals, states, false // ); } } // // Check Delay Between Two Signals ... bool IsSignalDelayPassed( XSignal &signal // ) { // bool result = false; // // Check Signal Validation ... result = signal.IsValid(); if (!result) { return result; } // // Check Delay Signals Allowed ... int delay = DelayBetweenTwoSignal(); result = delay <= 0; if (result) { return result; } // // Retrieve Positions ... // Based On Provider and Symbol and TimeFrame ... XPosition positions[]; int positionsCount = mTrader.GetPositions( positions, signal.symbol, NULL, // signal.provider, NULL, // signal.period, ToPositionType(signal.type), true // Filter By Magic ... ); result = !IsValidSize(positionsCount); if (result) { return result; } // XPosition youngest; int youngestAge = GetYoungest( youngest, positions // ); result = youngestAge >= delay; // return result; } // bool IsMarginPassed() { // double freeMargin = mTrader.mAccount.GetFreeMargin(); double minFreeMargingForHandleForce = MinFreeMargingForHandleForce(); // bool result = minFreeMargingForHandleForce <= 0 ? true : freeMargin >= minFreeMargingForHandleForce; // return result; } // bool IsNumberOfPositionsPassed() { // bool result = false; // // int maxAllowed = MaxPositionsForce(); // result = maxAllowed <= 0; // if (result) // { // return result; // } // // // XPosition positions[]; // int positionsCount = mTrader.GetPositions(positions); // result = !IsValidSize(positionsCount); // if (result) // { // return result; // } // // // result = positionsCount < maxAllowed; // result = true; // return result; } // // Private ... private: // // Props ... // // Signals ... bool mAllowLong; // Allow Long bool mAllowShort; // Allow Short int mReuiredSignalVerifications; // Required Verifications for Validate Signals bool mExecuteSignalsOnBreakout; // Execute Signals On Breakouts bool mGetVerificationFromOtherTimeFrames; // Get Verifications from Other Time Frames // // Risk Management ... double mVolume; // Volume double mTPPoint; // TP Point double mSLPoint; // SL Point int mMaxAllowedTrades; // Max Alloed Positions bool mUseMaxAllowedPerDirection; // Use Max Allowed Positions Per Direction bool mIgnoreTP; // Ignore Calculated TP bool mIgnoreSL; // Ignore Calculated SL // // Signalling ... bool mCloseOnOpposit; // Close all Positions on Opposit int mEndSignallingHoure; // End Signalling at Specific Time int mCloseOnSpecificTime; // Close All Trades in Specific Time int mStartSignallingHoure; // Start Signalling at Specific Time // // Force State: // we can do many things in force state: // - Prepare Force Hedging; // - Receive Signals with minimal Verifications; // - Increase Volume Size of in Profit Positions; // - etc ... // bool mForceState; // Determine in Force State or not int mDelayBetweenTwoSignal; // Delay between two same signal int mMaxPositionsForce; // Max Number of Positions For Guard Handling double mMaxDrawdownForce; // Force Handling State on Drawdown for Guard bool mAllowSymbolHedgeOnForce; // Allow Symbol Hedging on Force States double mMinFreeMargingForHandleForce; // Min Free Margin for Force States // XTradeHandler *mTradeHandler; // Handle all Event which related to Signals and Positions // // Apply Default Configurations ... void DefaultConfigs() { // // Signals ... AllowLong(false); AllowShort(false); ReuiredSignalVerifications(0); GetVerificationFromOtherTimeFrames(false); // // Risk Management ... TPPoint(0); SLPoint(0); Volume(0.01); IgnoreTP(false); IgnoreSL(false); MaxAllowedTrades(0); // // Signalling ... CloseOnOpposit(false); EndSignallingHoure(-1); CloseOnSpecificTime(-1); StartSignallingHoure(-1); // // Trailling ... AllowTrailStop(false); NextTrailPoint(0); FirstTrailPoint(0); NextTrailDistance(0); FirstTrailDistance(0); // // Supporting ... AllowSupport(false); MaxNumberOfSupports(0); SupportVolumeMultiplier(0.01); MaxAllowedSupportVolume(0.08); // // Grid ... AllowGrid(false); GridDistance(0); MaxNumberOfGrids(0); GridVolumeMultiplier(0.01); MaxAllowedGridVolume(0.08); // // Recovery ... AllowRecovery(false); MaxNumberOfRecoveries(0); RecoveryDistance(0); RecoveryVolumeMultiplier(0.01); MaxAllowedRecoveryVolume(0.08); // SaveResults(false); } // 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; } // int FindSetupIndex( string symbol // ) { // 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) { // result = i; break; } } // return result; } // // EQM Functions ... // // Force Close All Positions Due EQM Hedge ... bool DoEQMForceClose() { // bool result = false; // XPosition positions[]; int positionsCount = mTrader.GetPositions(positions); result = IsValidSize(positionsCount); if (!result) { return result; } // double profit = SpecifiedCalculatePositionsProfit( positions // ); // string comment = XEQMSupportToken + " Hedge ..."; int closed = Close( positions, comment // ); // result = IsValidSize(closed); if (result) { // mTradeHandler.Sync(); EQMClearAllForceStates(); } // // Handle Sleeping ... int restingTime = RestingAfterHedge(); if (result && IsValidSize(restingTime)) { Sleeping(restingTime); } // return result; } // // Do Gridding Mechanism ... void DoEQMProtect() { // XSignal supports[]; int supportsCount = mTradeHandler.DoProtect( supports, mSetups); // if (IsValidSize(supportsCount)) { EQMExecuteSignals(supports); } } // // Handle Close Trades on Specific Time ... void DoEQMCloseOnSpecificTime() { // bool canClose = CanCloseOnTime(); if (!canClose) { return; } // XPosition positions[]; int positionsCount = mTrader.GetPositions(positions); if (!IsValidSize(positionsCount)) { return; } // string comment = XEQMSupportToken + " Close On Specific Time ..."; // int closed = Close( positions, comment // ); if (IsValidSize(closed)) { // string message = XEQMSupportToken + " Closed " + ToString(closed) + " Positions on Specified Time ..."; // Alert(message); } } // // Handle Force State Management ... void EQMHandleForceState() { // XPosition positions[]; int positionsCount = mTrader.GetPositions(positions); if (!IsValidSize(positionsCount)) { // EQMClearAllForceStates(); // return; } // // Search For Force State Per Each Setup ... // int forceCount = 0; int setupsCount = CountSetups(); if (IsValidSize(setupsCount)) { // int maxAllowed = MaxAllowedTrades(); bool perDirection = UseMaxAllowedPerDirection(); // for (int i = 0; i < setupsCount; i++) { // string iSymbol = mSetups[i].GetSymbol(); ENUM_TIMEFRAMES iPeriod = mSetups[i].GetPeriod(); // XPosition iPositions[]; int iPositionsCount = mTrader.GetPositions( iPositions, iSymbol, NULL, // All Providers ... NULL, // All Periods ... NULL, // All Types ... true // Filter By Magic ... ); if (!IsValidSize(iPositionsCount)) { continue; } // // Counting Positions ... int longs; double longProfits; double longVolumes; // int shorts; double shortProfits; double shortVolumes; // CountPositions( iPositions, // longs, longProfits, longVolumes, // shorts, shortProfits, shortVolumes // ); // bool isMaxReached = maxAllowed <= 0 ? false : !perDirection ? longs + shorts >= maxAllowed : longs >= maxAllowed && shorts >= maxAllowed; double volumeSummary = longVolumes + shortVolumes; double profitsSummary = longProfits + shortProfits; // bool isIInForce = // maxAllowed <= 0 ? profitsSummary < 0 && longVolumes == shortVolumes : isMaxReached && profitsSummary < 0 && longVolumes == shortVolumes // ; if (isIInForce) { // forceCount++; mSetups[i].ForceState(true); } } } // bool isForce = forceCount >= 1; if (!isForce) { return; } // } // // Handle any Invalid Signals ... void EQMHandleInvalidSignal( XSignal &signal, // Invalid Signal int pushers, // Pushers bool isValid, // IsValid Signal ... X121SetupConditions &conditions[] // All Time Frames Conditions ) { // // Check Force State ... // if (!ForceState()) // { // return; // } // int setupIDX = FindSetupIndex(signal.symbol); if (!IsValidIndex(setupIDX)) { return; } // bool isForce = mSetups[setupIDX].ForceState(); if (!isForce) { return; } // // Check Delay Between Two Signals ... bool isMarginPassed = IsMarginPassed(); bool isDelayPassed = IsSignalDelayPassed(signal); bool isNumberOfPositionsPassed = IsNumberOfPositionsPassed(); bool canUseSignal = isMarginPassed && isDelayPassed && isNumberOfPositionsPassed; // XSignal signals[]; // if (isValid) { // bool canSupport = // EnableSupport() && SupportOnlyForces() // ; bool canGrid = // EnableGrid() && GridOnlyForces() // ; bool canRecover = // EnableRecovery() && RecoverOnlyForces() // ; // if (canUseSignal) { // AddRef( signal, signals // ); // // Add new Signal Info ... mTradeHandler.Add( signal, pushers, canGrid, canRecover, canSupport, conditions[0], conditions[1], conditions[2], conditions[3], conditions[4] // ); } } // if (ArraySize(signals) > 0) { EQMExecuteSignals(signals); } } // void EQMExecuteSignals( XSignal &signals[] // ) { // int signalsCount = ArraySize(signals); if (!IsValidSize(signals)) { return; } // // // Execute Supports ... ENUM_X_SIGNAL_EXECUTION_RESULT states[]; int executed = ExecuteSignals( signals, states, false // Ignore Policies ... ); if (executed != signalsCount) { // // TODO: Dow What We Want ... // Print("Error On Executing Support Signal ..."); } // // Remove Supported Signals TP and SL and leave them for Handling using HEDGE Mechanism ... if (IsValidSize(executed)) { // for (int i = 0; i < signalsCount; i++) { // ENUM_X_SIGNAL_EXECUTION_RESULT iState = states[i]; if (iState != X_SIGNAL_EXECUTION_SUCCEED) { continue; } // XSignal iSignal = signals[i]; if (!iSignal.IsValid() || !iSignal.IsExecuted()) { continue; } // ulong iParentTicket = ExtractParentTicket(iSignal.comment); if (iParentTicket <= 0) { continue; } // XPosition iParent; bool hasParent = mTrader.GetPosition( iParentTicket, iParent // ); if (!hasParent) { continue; } // // Check Parent Has TP or SL ... if (iParent.tp == 0 && iParent.sl == 0) { continue; } // // Remove TP and SL of Supported Positions ... string comment = "EQM Remove TPSL ..."; bool isModified = Modify( iParentTicket, 0, 0, comment // ); if (isModified) { // // TODO: // do What we want ... } } } } // void EQMClearAllForceStates() { // int setupsCount = CountSetups(); if (!IsValidSize(setupsCount)) { return; } // for (int i = 0; i < setupsCount; i++) { mSetups[i].ForceState(false); } } // }; //