diff --git a/Classes/x-saherelm.x-trade-manager.class.mq5 b/Classes/x-saherelm.x-trade-manager.class.mq5 new file mode 100644 index 00000000..980e5360 --- /dev/null +++ b/Classes/x-saherelm.x-trade-manager.class.mq5 @@ -0,0 +1,2205 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XCXTradeManager +// Description: provides all Trade Management requirements ... +// +// +// 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.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-data.collector.class.mq5" +#include "../Classes/x-saherelm.x-guard.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +// Implementation ... +class XCTradeManager : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAlert *alert; + XCGuard *guard; + XCTrade *trader; + XTimeTracker timeTracker; + XCDataCollector *collector; + + // + // Constructor ... + XCTradeManager( + XCAlert *_alert, + XCTrade *_trader, + XCGuard *_guard // + ) + { + // + alert = _alert; + guard = _guard; + trader = _trader; + + // + allowTrade = true; + allowLongs = true; + allowShorts = true; + + // + forceCloseAt = NULL; + isForceCloseAtTime = false; + + // + maxAllowedTPs = 0; + maxAllowedSLs = 0; + maxAllowedTrades = 0; + restrictionsPeriod = XTRADE_RESTRICATION_NONE; + + // + reportTrades = true; + reportSignals = true; + reportProtector = true; + reportAfterTradesBalance = true; + + // + SaveTrades(false); + + // + collector = new XCDataCollector(); + + // + // Setting Collector Path ... + string mPath = (IsValid(alert.GetPrefix()) + ? alert.GetPrefix() + "\\" + : "") + + trader.mAccount.GetCompany(); + collector.Path(mPath); + } + + // + // Deconstructor ... + ~XCTradeManager() + { + // + Clean(trades); + + // + timeTracker.Clean(); + + // + ZeroMemory(alert); + ZeroMemory(trader); + + // + delete collector; + ZeroMemory(collector); + } + + // + // Properties ... + + // + bool SaveTrades() + { + return mSaveTrades; + } + + // + void SaveTrades(bool value) + { + mSaveTrades = value; + } + + // + bool SaveSignals() + { + return mSaveSignals; + } + + // + void SaveSignals(bool value) + { + mSaveSignals = value; + } + + // + bool SaveWins() + { + return mSaveWins; + } + + // + void SaveWins(bool value) + { + mSaveWins = value; + } + + // + bool SaveLosts() + { + return mSaveLosts; + } + + // + void SaveLosts(bool value) + { + mSaveLosts = value; + } + + // + bool SaveRestrictions() + { + return mSaveRestrictions; + } + + // + void SaveRestrictions(bool value) + { + mSaveRestrictions = value; + } + + // + // Setter(s) ... + + // + void SetForceCloseTradesAt( + string _forceCloseAt // + ) + { + forceCloseAt = _forceCloseAt; + } + + // + void SetTradeSession( + string symbol, + string start, + string end, + string name = NULL // + ) + { + // + // Validate Args ... + bool has = IsValid(end) && + IsValid(start) && + IsValid(symbol); + if (!has) + { + return; + } + + // + // Create Session ... + + // + XTradeSession session; + + // + session.end = end; + session.name = name; + session.start = start; + + // + int sessionIDX = -1; + has = FindSymbolSession( + sessionIDX, + symbol // + ); + + // + if (!has) + { + // + // Add New Symbol Session ... + + // + XSymbolSessions iSymbolSession; + iSymbolSession.symbol = symbol; + + // + AddTradingSession( + session, + iSymbolSession // + ); + + // + AddRef( + iSymbolSession, + sessions // + ); + + // + iSymbolSession.Clean(); + } + else + { + // + // Update Trading Sessions of Exists Symbol Session ... + AddTradingSession( + session, + sessions[sessionIDX] // + ); + } + + // + // Cleanup Resources ... + session.Clean(); + } + + // + void SetTradeReports( + bool _reportTrades, + bool _reportSignals, + bool _reportProtector, + bool _reportRestrictions, + bool _reportAfterTradesBalance // + ) + { + // + reportTrades = _reportTrades; + reportSignals = _reportSignals; + reportProtector = _reportProtector; + reportRestrictions = _reportRestrictions; + reportAfterTradesBalance = _reportAfterTradesBalance; + } + + // + void SetTradePermissions( + bool _allowTrade, + bool _allowLongs, + bool _allowShorts // + ) + { + // + allowTrade = _allowTrade; + allowLongs = _allowLongs; + allowShorts = _allowShorts; + } + + // + void SetTradeRestrictions( + ENUM_XTRADE_RESTRICTION_PERIOD _period, + int _maxAllowedTPs, + int _maxAllowedSLs, + int _maxAllowedTrades // + ) + { + // + // Normalizing Args ... + _maxAllowedTPs = NormalizeInt(_maxAllowedTPs, 0); + _maxAllowedSLs = NormalizeInt(_maxAllowedSLs, 0); + _maxAllowedTrades = NormalizeInt(_maxAllowedTrades, 0); + + // + restrictionsPeriod = _period; + maxAllowedTPs = _maxAllowedTPs; + maxAllowedSLs = _maxAllowedSLs; + maxAllowedTrades = _maxAllowedTrades; + } + + // + // Tools and Helpers ... + + /** + * Do All Position Managing Senaros ... + */ + void Manage() + { + // + // Handle Restrictions ... + HandleRestrictions(); + + // + // Check Contains Trades for Managing ... + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + // Update Required Infos of Trades ... + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + // Update Trade Data ... + trades[i].swap = iPosition.swap; + trades[i].profit = iPosition.profit; + } + + // + // Do Trade Protection ... + Protect(); + } + + /** + * Do All Position Protection Here ... + */ + void Protect() + { + // + string prefix = "Protector: "; + int targetDistance = 5; + + // + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + XPosition ownPosition[]; + XPosition ownLongPosition[]; + XPosition ownShortPosition[]; + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = + trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + AddRef( + iPosition, + ownPosition // + ); + + // + if (IsLong(iPosition.type)) + { + // + AddRef( + iPosition, + ownLongPosition // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPosition // + ); + } + } + + // + has = HasChild(ownPosition); + if (!has) + { + // + Clean(ownPosition); + Clean(ownLongPosition); + Clean(ownShortPosition); + + // + return; + } + + // + double swapSum = 0; + double profitSum = 0; + double commissionSum = 0; + + // + // Calculate Required Data On Collection ... + count = ArraySize(ownPosition); + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPosition[i]; + + // + swapSum += iPosition.swap; + profitSum += iPosition.profit; + commissionSum += iPosition.commission; + } + + // + // Do Collection Protectiong ... + + // + // Check Force Close ... + if (IsValid(forceCloseAt)) + { + // + datetime forceCloseTime = ParseDateTimeFromTimeString(forceCloseAt); + bool canForceClose = IsTimeInRange( + TimeCurrent(), + forceCloseTime // + ) && + !isForceCloseAtTime; + if (canForceClose) + { + // + isForceCloseAtTime = HandleForceCloseTrades(ownPosition); + + // + // Prevent Moving Forward ... + return; + } + } + + // + // Do Signle Protections ... + for (int i = 0; i < count; i++) + { + // + // Select Position ... + XPosition iPosition = ownPosition[i]; + int idx = -1; + has = HasTrade( + idx, + iPosition.ticket // + ); + if (!has) + { + continue; + } + + // + bool isLong = IsLong(iPosition.type); + double points = GetPoints(iPosition.symbol); + + // + // Handle RF On Targets ... + if (iPosition.profit > 0) + { + // + // Handle Risk Free On Targets ... + XTarget targets[]; + Copy( + trades[idx].signal.targets, + targets // + ); + int targetsCount = ArraySize(targets); + has = IsValidSize(targetsCount); + if (has) + { + // + for (int j = 0; j < targetsCount; j++) + { + // + XTarget jTarget = targets[j]; + + // + int appliedTargetIDX = -1; + + // + // Check Target is Applied Before or Not ... + has = + !trades[idx].signal.isTargetApplied + ? true + : trades[idx].signal.appliedTargetIDX < j; + if (!has) + { + continue; + } + + // + // Check Traget Validation ... + has = + iPosition.sl == 0 + ? true + : isLong + ? iPosition.sl < jTarget.target + : iPosition.sl > jTarget.target; + if (!has) + { + continue; + } + + // + double targetDelta = isLong + ? jTarget.target + (targetDistance * points) + : jTarget.target - (targetDistance * points); + + // + // Can Risk Free ... + bool canRF = + jTarget.doRF && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + + // + // Can Partial Close ... + bool canPC = + jTarget.volumeMultiplier > 0 && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + bool canRFPC = canRF || + canPC; + if (canRFPC) + { + // + // Handle Risk Free ... + bool isRFDone = false; + if (canRF) + { + // + double tp = iPosition.tp; + double sl = jTarget.target; + string comment = "RF On Target ..."; + isRFDone = trader.Modify( + iPosition.ticket, + sl, + tp, + comment // + ); + } + + // + // Handle Partail Close ... + bool isPCDone = false; + if (canPC) + { + // + double volume = jTarget.volumeMultiplier * iPosition.volume; + volume = NormalizeVolume(volume, iPosition.symbol); + string comment = "RF On Target ..."; + isPCDone = trader.ClosePartial( + iPosition.ticket, + volume, + comment // + ); + } + + // + // Handle Report Action ... + bool isRFPCDone = isRFDone || + isPCDone; + if (isRFPCDone) + { + // + trades[idx].signal.appliedTargetIDX = j; + trades[idx].signal.isTargetApplied = true; + + // + string message = prefix + + ToXString(iPosition.type) + + " Position: " + + ToXString(iPosition.ticket) + + (isRFDone ? " RF" : "") + + (isPCDone ? " PC" : "") + + " On Traget: " + ToXString(jTarget.target) + + " Successfully ..."; + HandleReportProtector(message); + } + } + } + } + } + } + } + + /** + * Check Specified Symbol is Active for + * Analysing or Open Trades ... + */ + bool IsActiveSession(string symbol) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + result = sessions[symbolSessionIDX].CanTrade(); + } + + // + return result; + } + + /** + * Check Signal Execution Conditions ... + * + * @param signal: XSignal instance reference ... + * @param executionResult: ENUM_X_SIGNAL_EXECUTION_RESULT member reference ... + * + * @return ( bool ) + */ + bool CheckSignal( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &executionResult // + ) + { + // + bool result = false; + + // + // Cleanup ... + executionResult = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Reporting Signal ... + if (reportSignals) + { + // + string message = signal.GetMessage("Provided"); + alert.SendAlert(message); + } + + // + SaveSignal(signal); + + // + // Check Trade Permission ... + if (!allowTrade) + { + // + result = false; + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + bool isLong = IsLong(signal.type); + bool isShort = IsShort(signal.type); + + // + bool isLongAndAllowed = + isLong && + allowLongs; + + // + bool isShortAndAllowed = + isShort && + allowShorts; + + // + result = isLongAndAllowed || + isShortAndAllowed; + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + // Check Symbol Info Exists or not ... + int symbolInfoIDX = -1; + bool isSymbolInfoExists = FindSymbolIndex( + symbolInfoIDX, + signal.symbol // + ); + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + signal.symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + // + result = sessions[symbolSessionIDX].CanTrade(); + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + + // + return result; + } + } + + // + // Check Trade Permissions Based on SL(s) Count ... + bool hasRestrictions = restrictionsPeriod != XTRADE_RESTRICATION_NONE; + if (hasRestrictions) + { + // + // Only Can Check Restrictions when + // Symbol Info Exists ... + if (isSymbolInfoExists) + { + // + bool isTPAllowed = maxAllowedTPs == 0 + ? true + : symbols[symbolInfoIDX].managedTPs < maxAllowedTPs; + bool isSLAllowed = maxAllowedSLs == 0 + ? true + : symbols[symbolInfoIDX].managedSLs < maxAllowedSLs; + bool isTradeAllowed = maxAllowedTrades == 0 + ? true + : symbols[symbolInfoIDX].managedTrades < maxAllowedTrades; + + // + result = isTPAllowed && + isSLAllowed && + isTradeAllowed; + } + + // + // Report Error ... + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + + // + return result; + } + } + + // + return result; + } + + /** + * Execute Specified Signal ... + * + * @param signal: XSignal instance reference ... + * @param conditions: XCATBEAStrategyConditions instance reference ... + * + * @return ( bool ) + */ + bool Execute( + XSignal &signal, + string conditions // + ) + { + // + bool result = false; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = HasTrade( + idx, + signal // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT executionResult; + + // + // Checking Signal For Execution ... + result = CheckSignal( + signal, + executionResult // + ); + if (result) + { + // + result = trader.ExecuteSignal( + signal, + executionResult // + ); + } + + // + // Alert Signal Execution ... + if (reportTrades) + { + // + string executionMessage = ToString(executionResult); + + // + string message = NULL; + if (result) + { + message = signal.GetMessage("Executed"); + } + else + { + message = signal.GetMessage("Failed due (" + executionMessage + ")"); + } + + // + alert.SendAlert(message); + } + + // + if (result) + { + // + // Draw Signal ... + // if (drawSignal) + // { + // // + // XCSignalObject *iObj; + // isExists = drawer.DrawSignal( + // signal, + // iObj // + // ); + + // // + // if (isExists) + // { + // // + // mObjects.Add(iObj); + // ZeroMemory(iObj); + // } + // } + + // + // Create Symbol Info Struct ... + XTradeSymbolInfo iSymbolInfo; + + // + iSymbolInfo.trades = 1; + iSymbolInfo.managedTrades = 1; + iSymbolInfo.symbol = signal.symbol; + + // + bool isLong = IsLong(signal.type); + if (isLong) + { + iSymbolInfo.longs = 1; + } + else + { + iSymbolInfo.shorts = 1; + } + + // + // Fill Balance for Restrications ... + bool hasRestrictions = HasRestrictions(restrictionsPeriod); + if (hasRestrictions) + { + // + // Read Balance ... + double balance = trader.mAccount.GetBalance(); + iSymbolInfo.managedBalance = balance; + iSymbolInfo.managedStart = TimeCurrent(); + } + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + // Create Trade Struct ... + XTradeInfo iTrade; + + // + ulong positionID = trader.GetLastOpenPositionTicket(); + double commission = trader.GetPositionCommission(positionID); + + // + iTrade.signal = signal; + iTrade.conditions = conditions; + iTrade.positionID = positionID; + iTrade.commission = commission; + iTrade.signaledAt = signal.time; + iTrade.executedAt = TimeCurrent(); + + // + AddRef( + iTrade, + trades // + ); + } + + // + return result; + } + + /** + * Retrieve Specified Positions ... + * + * @param positions: XPosition instance Reference Array, which holds Founded Positions ... + * @param symbol: string, Specified Symbol Name ... + * @param provider: string, Specified Provider Name ... + * @param period: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int GetPositions( + XPosition &positions[], + string symbol, + string provider, + ENUM_TIMEFRAMES period // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = + IsValid(symbol) && + IsValid(period) && + IsValid(provider); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + symbol, + provider, + period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + /** + * Handle Position Take Profit ... + * + * @param deal: XDeal instance reference ... + */ + void HandleTP(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XTRADE_FINAL_TP; + + // + // Save Trade ... + SaveWin(trades[idx]); + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "TP: " + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + XTradeSymbolInfo iSymbolInfo; + + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Stop Loss ... + * + * @param deal: XDeal instance reference ... + */ + void HandleSL(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XTRADE_FINAL_SL; + + // + // Save Trade ... + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "SL: " + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + bool isInProfit = trades[idx].profit > 0; + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + XTradeSymbolInfo iSymbolInfo; + + // + if (isInProfit) + { + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + } + else + { + // + iSymbolInfo.losses = 1; + iSymbolInfo.managedSLs = 1; + } + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Force Close ... + * + * @param deal: XDeal instance reference ... + */ + void HandleForceClose(const XPosition &position) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + position.ticket // + ); + if (!isExists) + { + return; + } + + // + bool isInProfit = position.profit > 0; + + // + // Apply Required Data ... + trades[idx].swap = position.swap; + trades[idx].profit = position.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].commission = position.commission; + trades[idx].finalize = isInProfit + ? XTRADE_FINAL_CLOSE_IN_PROFIT + : XTRADE_FINAL_CLOSE_IN_LOSE; + + // + // Save Trade ... + SaveTrade(trades[idx]); + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + // Handle Balance Reporting ... + string prefix = "Force Close " + + (isInProfit + ? "Profit" + : "Loss") + + ": " + + ToXString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + XTradeSymbolInfo iSymbolInfo; + + // + if (isInProfit) + { + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + } + else + { + // + iSymbolInfo.losses = 1; + iSymbolInfo.managedSLs = 1; + } + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ULONG ... + * @param profit: double ... + * @param comment: string ... + */ + void HandlePartiallyClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + // Handle Balance Reporting ... + string prefix = "Partially Closed: " + ToXString(ticket); + + // + // Handle Balance Reporting ... + HandleReportBalance(prefix); + } + + /** + * Handle Force Close Trades ... + */ + bool HandleForceCloseTrades( + XPosition &positions[] // + ) + { + // + bool result = false; + + // + result = HasChild(positions); + if (!result) + { + return result; + } + + // + string prefix = "Protector: "; + string comment = "Force Close ..."; + + // + int closedsCount = trader.Close( + positions, + comment // + ); + result = IsValidSize(closedsCount); + if (result) + { + // + string message = prefix + "Force Close (" + ToXString(closedsCount) + ") Trades at Specified Time ..."; + HandleReportProtector(message); + } + + // + return result; + } + + // + // TODO: Complete this ... + void HandleGuard() + { + } + + /** + * Find Executed Trade by Providing Position Ticket ... + * + * @param index: int reference, holding founded item index ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + ulong ticket // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + ticket > 0 && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XTradeInfo iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.IsExecuted() && + iTrade.positionID == ticket; + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Find Trade Item By Signal ... + * + * @param index: int reference, holding founded item index ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + XSignal &signal // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + signal.IsValid() && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XTradeInfo iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.signal.IsSameAs(signal); + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Remove a Trade From List ... + * + * @param index: int ... + */ + void RemoveTrade(int index) + { + // + bool has = + HasChild(trades) && + IsValidIndex(index) && + index < ArraySize(trades); + if (!has) + { + return; + } + + // + ArrayRemove( + trades, + index, + 1 // + ); + } + + // + // Protected ... + protected: + // + // Tools ... + + // + string GetTradeFilePath(XTradeInfo &trade) + { + // + string fileName = trade.GetFileName(); + + // + return GetTradeFilePath(fileName); + } + + // + string GetTradeFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Trades" + "\\" + fileName); + + // + return result; + } + + // + string GetSignalFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Signals" + "\\" + fileName); + + // + return result; + } + + // + string GetWinsFilePath(XTradeInfo &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToXString(trade.signal.period) + "_wins"); + + // + return result; + } + + // + string GetLostsFilePath(XTradeInfo &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToXString(trade.signal.period) + "_losts"); + + // + return result; + } + + // + string GetRestrictionsFilePath(string symbol) + { + // + string result = NULL; + + // + if (!IsValid(symbol)) + { + return result; + } + + // + result = collector + .GetFilePath("Restrictions" + "\\" + symbol); + + // + return result; + } + + // + void HandleReportBalance(string prefix = NULL) + { + // + if (!reportAfterTradesBalance) + { + return; + } + + // + double balance = trader.mAccount.GetBalance(); + string currency = trader.mAccount.GetCurrency(); + + // + string message = + (IsValid(prefix) + ? prefix + " | " + : "") + + "Account Balance: " + ToXString(balance) + currency; + alert.SendAlert(message); + } + + // + void HandleReportProtector(string message = NULL) + { + // + if (!reportProtector) + { + return; + } + + // + alert.SendAlert(message); + } + + // + // Save Trades ... + bool SaveTrade( + XTradeInfo &trade, + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + bool result = false; + + // + if (!mSaveTrades) + { + return result; + } + + // + string filePath = GetTradeFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = trade.ToString( + includeSummary, + includeSignal, + includeConditions // + ); + + // + result = collector.Save( + filePath, + content // + ); + + // + return result; + } + + // + // Save Signals ... + bool SaveSignal(XSignal &signal) + { + // + bool result = false; + + // + // Check Signal Save is Enabled ... + if (!mSaveSignals) + { + return result; + } + + // + // Check Signal Validation ... + if (!signal.IsValid()) + { + return result; + } + + // + // Retrieve Signal File Name ... + string signalFileName = signal.GetFileName(); + result = IsValid(signalFileName); + if (!result) + { + return result; + } + + // + // Retriev and Validate File Name ... + string filePath = GetSignalFilePath(signalFileName); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Generate Content ... + string content = ""; + content += + ToXString("----------------") + "\n" + + ToXString("Signal: ") + "\n" + + ToXString("----------------") + "\n" + + signal.ToString() + "\n"; + content += + ToXString("----------------") + "\n" + + ToXString("Conditions: ") + "\n" + + ToXString("----------------") + "\n" + + signal.conditions + "\n"; + + // + // Save Content to File ... + result = collector.Save( + filePath, + content // + ); + + // + // Return Result ... + return result; + } + + // + bool SaveWin(XTradeInfo &trade) + { + // + bool result = false; + + // + if (!mSaveWins) + { + return result; + } + + // + string filePath = GetWinsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + bool SaveLost(XTradeInfo &trade) + { + // + bool result = false; + + // + if (!mSaveLosts) + { + return result; + } + + // + string filePath = GetLostsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + bool SaveRestrictions(XTradeSymbolInfo &info) + { + // + bool result = false; + + // + if (!mSaveRestrictions) + { + return result; + } + + // + result = info.IsValid(); + if (!result) + { + return result; + } + + // + string filePath = GetRestrictionsFilePath(info.symbol); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = info.GetRestrictionDescription(restrictionsPeriod); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + // Symbol Info ... + + // + bool FindSymbolIndex( + int &index, + XTradeSymbolInfo &item // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + result = HasChild(symbols); + if (!result) + { + return result; + } + + // + index = FindIndex( + item, + symbols // + ); + + // + result = IsValidIndex(index); + + // + return result; + } + + // + bool FindSymbolIndex( + int &index, + string symbol // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(symbols); + if (!result) + { + return result; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + result = symbols[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + void AddOrUpdateSymbolInfo(XTradeSymbolInfo &item) + { + // + bool has = item.IsValid(); + if (!has) + { + return; + } + + // + int index = -1; + bool isExists = FindSymbolIndex( + index, + item // + ); + if (!isExists) + { + // + AddRef( + item, + symbols // + ); + } + else + { + // + symbols[index].longs += item.longs; + symbols[index].shorts += item.shorts; + symbols[index].trades += item.trades; + symbols[index].losses += item.losses; + symbols[index].profits += item.profits; + symbols[index].managedSLs += item.managedSLs; + symbols[index].managedTPs += item.managedTPs; + symbols[index].managedTrades += item.managedTrades; + symbols[index].managedProfits += item.managedProfits; + + // + // Handle Remove on Managed SL based On Managed TP ... + if (item.managedTPs > 0) + { + // + symbols[index].managedSLs -= item.managedTPs; + if (symbols[index].managedSLs < 0) + { + symbols[index].managedSLs = 0; + } + } + + // + // Handle Remove on Managed TP based On Managed SL ... + if (item.managedSLs > 0) + { + // + symbols[index].managedTPs -= item.managedSLs; + if (symbols[index].managedTPs < 0) + { + symbols[index].managedTPs = 0; + } + } + } + } + + // + void ResetSymbolsRestrictions() + { + // + bool has = HasChild(symbols); + if (has) + { + // + string prefix = "Protector: "; + + // + datetime start = TimeCurrent(); + double balance = trader.mAccount.GetBalance(); + bool hasRestrictions = HasRestrictions(restrictionsPeriod); + if (!hasRestrictions) + { + // + balance = 0; + start = NULL; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + XTradeSymbolInfo iInfo = symbols[i]; + if (reportRestrictions) + { + // + string message = iInfo.GetRestrictionDescription(restrictionsPeriod); + alert.SendAlert(message); + } + SaveRestrictions(iInfo); + + // + symbols[i].managedSLs = 0; + symbols[i].managedTPs = 0; + symbols[i].managedTrades = 0; + symbols[i].managedProfits = 0; + symbols[i].managedStart = start; + symbols[i].managedBalance = balance; + + // + iInfo.Clean(); + } + + // + string message = prefix + "Reset Symbols Restrictions"; + HandleReportProtector(message); + } + } + + // + void HandleRestrictions() + { + // + bool isNewDay = timeTracker.IsNewDay(); + bool isNewHour = timeTracker.IsNewHour(); + bool isNewWeek = timeTracker.IsNewWeek(); + bool isNewMonth = timeTracker.IsNewMonth(); + + // + // Reset Force Closed Flag on new Day Starts ... + if (isNewDay) + { + isForceCloseAtTime = false; + } + + // + bool canResetRestrictions = + ( + // + // Hourly ... + (isNewHour && + restrictionsPeriod == XTRADE_RESTRICATION_HOURLY) + // + || + // + // Daily ... + (isNewDay && + restrictionsPeriod == XTRADE_RESTRICATION_DAILY) + // + || + // + // Weekly ... + (isNewWeek && + restrictionsPeriod == XTRADE_RESTRICATION_WEEKLY) + // + || + // + // Monthly ... + (isNewMonth && + restrictionsPeriod == XTRADE_RESTRICATION_MONTHLY) + // + ) + // + ; + if (canResetRestrictions) + { + ResetSymbolsRestrictions(); + } + } + + // + // Symbol Session ... + + // + bool FindSymbolSession( + int &index, + string symbol // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(sessions); + if (!result) + { + return result; + } + + // + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + void AddTradingSession( + XTradeSession &session, + XSymbolSessions &symbolSession // + ) + { + // + bool has = session.IsValid() && + symbolSession.IsValid(); + if (!has) + { + return; + } + + // + // Check Session Exists in Symbol Session ... + bool isExists = false; + if (HasChild(symbolSession.sessions)) + { + // + int count = ArraySize(symbolSession.sessions); + for (int i = 0; i < count; i++) + { + // + isExists = symbolSession.sessions[i].end == session.end && + symbolSession.sessions[i].start == session.start; + if (isExists) + { + break; + } + } + } + + // + if (!isExists) + { + // + AddRef( + session, + symbolSession.sessions // + ); + } + } + + // + // Private ... + private: + // + // Props ... + + // + bool allowTrade; + bool allowLongs; + bool allowShorts; + + // + string forceCloseAt; + bool isForceCloseAtTime; + + // + int maxAllowedTPs; + int maxAllowedSLs; + int maxAllowedTrades; + ENUM_XTRADE_RESTRICTION_PERIOD restrictionsPeriod; + + // + bool mSaveWins; + bool mSaveLosts; + bool mSaveTrades; + bool mSaveSignals; + bool mSaveRestrictions; + + // + bool reportTrades; + bool reportSignals; + bool reportProtector; + bool reportRestrictions; + bool reportAfterTradesBalance; + + // + XTradeInfo trades[]; + XTradeSymbolInfo symbols[]; + XSymbolSessions sessions[]; +}; \ No newline at end of file diff --git a/Experts/x-saherelm.xom1.ea.mq5 b/Experts/x-saherelm.xom1.ea.mq5 index 9aef09e7..ccd43920 100644 --- a/Experts/x-saherelm.xom1.ea.mq5 +++ b/Experts/x-saherelm.xom1.ea.mq5 @@ -35,6 +35,67 @@ input long eaMagicNumber = 1694056; // Magic Number input int eaSlippage = 10; // Slippgae input string eaLogSuffix = ""; // Log Suffix +// +// Management ... +// eaSessions => (ST_04:00_08:30),(TL_10:30_12:00),(NY_16:00_20:00) +input group "Management"; +input bool eaAllowGuards = false; // Allow Guards +input bool eaAllowTrade = true; // Allow Trade on Signals +input bool eaAllowLongs = true; // Allow Long Trades +input bool eaAllowShorts = true; // Allow Short Trades +input string eaSessions = ""; // Active Sessions +input ENUM_XTRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XTRADE_RESTRICATION_NONE; // Restrictions Period +input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) in Restrictions Period +input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) in Restrictions Period +input int eaMaxAllowedTrades = 0; // Max Allowed Trades in Restrictions Period +input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades +input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade +input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade +input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time + +// +// Volume ... +input group "Volume"; +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_CONSTANT; // Volume Applying Type +input double eaStaticVoluem = 0.0; // Static Volume +input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +input double eaConstantPercent = 1; // Constant Percent of Balance Per Trade +input double eaConstantBalance = 1000.0; // Constant Balance for Calculations + +// +// Alert ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaSaveAlerts = true; // Save Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = true; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Reports ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = true; // Report New Days +input bool eaReportNewHours = false; // Report New Hours +input bool eaReportTrades = true; // Report Trades +input bool eaReportSignals = true; // Report Signals +input bool eaReportRestrictions = true; // Report Restrictions +input bool eaReportProtector = true; // Report Protector Actions +input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished + +// +// Collector ... +input group "Collector"; +input bool eaSaveTrades = true; // Save Trades +input bool eaSaveSignals = true; // Save Signals +input bool eaSaveWins = true; // Save Winning Conditions +input bool eaSaveLosts = true; // Save Lost Conditions +input bool eaSaveRestrictions = true; // Save Restriction Reports + // // Variables ... @@ -78,14 +139,74 @@ int OnInit() // // Setting All Inputs to Expert Adviser Class ... + // + // Management ... + eaExpert.eaAllowGuards = eaAllowGuards; + eaExpert.eaAllowTrade = eaAllowTrade; + eaExpert.eaAllowLongs = eaAllowLongs; + eaExpert.eaAllowShorts = eaAllowShorts; + eaExpert.eaSessions = eaSessions; + eaExpert.eaRestrictionsPeriod = eaRestrictionsPeriod; + eaExpert.eaMaxAllowedTPs = eaMaxAllowedTPs; + eaExpert.eaMaxAllowedSLs = eaMaxAllowedSLs; + eaExpert.eaMaxAllowedTrades = eaMaxAllowedTrades; + eaExpert.eaMaxAllowedPositions = eaMaxAllowedPositions; + eaExpert.eaMaxAllowedSpread = eaMaxAllowedSpread; + eaExpert.eaMaxAllowedDrawdownFactor = eaMaxAllowedDrawdownFactor; + eaExpert.eaCloseAllOpenTradesAt = eaCloseAllOpenTradesAt; + + // + // Volume ... + eaExpert.eaVolumeSelect = eaVolumeSelect; + eaExpert.eaStaticVoluem = eaStaticVoluem; + eaExpert.eaDynamicVolumeStepBalance = eaDynamicVolumeStepBalance; + eaExpert.eaDynamicVolumeStepVolume = eaDynamicVolumeStepVolume; + eaExpert.eaConstantRiskBalance = eaConstantRiskBalance; + eaExpert.eaConstantPercent = eaConstantPercent; + eaExpert.eaConstantBalance = eaConstantBalance; + + // + // Alert ... + eaExpert.eaEnableAlerts = eaEnableAlerts; + eaExpert.eaSaveAlerts = eaSaveAlerts; + eaExpert.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Reports ... + eaExpert.eaReportNewMonths = eaReportNewMonths; + eaExpert.eaReportNewWeeks = eaReportNewWeeks; + eaExpert.eaReportNewDays = eaReportNewDays; + eaExpert.eaReportNewHours = eaReportNewHours; + eaExpert.eaReportTrades = eaReportTrades; + eaExpert.eaReportSignals = eaReportSignals; + eaExpert.eaReportRestrictions = eaReportRestrictions; + eaExpert.eaReportProtector = eaReportProtector; + eaExpert.eaReportAfterTradesBalance = eaReportAfterTradesBalance; + + // + // Collector ... + eaExpert.eaSaveTrades = eaSaveTrades; + eaExpert.eaSaveSignals = eaSaveSignals; + eaExpert.eaSaveWins = eaSaveWins; + eaExpert.eaSaveLosts = eaSaveLosts; + eaExpert.eaSaveRestrictions = eaSaveRestrictions; + + // + // Try to Initialize eaExpert ... bool isInited = eaExpert.HandleOnInit(); if (!isInited) { + // + Print(ShortName, ": Initialization Failed ..."); return INIT_FAILED; } // + Print(ShortName, ": Initialized Successfully ..."); return INIT_SUCCEEDED; } diff --git a/Helpers/x-saherelm.xom1.helper.mq5 b/Helpers/x-saherelm.xom1.helper.mq5 index 052cb97a..b461865f 100644 --- a/Helpers/x-saherelm.xom1.helper.mq5 +++ b/Helpers/x-saherelm.xom1.helper.mq5 @@ -31,26 +31,30 @@ // Buffers ... enum ENUM_XOM1_BUFFERS { - XOM1_MA_LINE = 0, - XOM1_MA_COLOR_LINE = 1, - XOM1_MA_STATE_LINE = 8, - XOM1_SAR_LINE = 2, - XOM1_SAR_COLOR_LINE = 3, - XOM1_SAR_STATE_LINE = 9, - XOM1_PEAK_LINE = 4, - XOM1_VALE_LINE = 5, - XOM1_FINO_UPPER_LINE = 6, - XOM1_FINO_LOWER_LINE = 7, - // 8 Ma State - // 9 Sar State - XOM1_SC_HH_LINE = 10, - XOM1_SC_LL_LINE = 11, - XOM1_MC_HH_LINE = 12, - XOM1_MC_LL_LINE = 13, - XOM1_LC_HH_LINE = 14, - XOM1_LC_LL_LINE = 15, - XOM1_HC_HH_LINE = 16, - XOM1_HC_LL_LINE = 17, + XOM1_MA_FAST_LINE = 0, + XOM1_MA_FAST_COLOR_LINE = 1, + XOM1_MA_FAST_STATE_LINE = 10, + XOM1_MA_SLOW_LINE = 2, + XOM1_MA_SLOW_COLOR_LINE = 3, + XOM1_MA_SLOW_STATE_LINE = 11, + XOM1_SAR_LINE = 4, + XOM1_SAR_COLOR_LINE = 5, + XOM1_SAR_STATE_LINE = 12, + XOM1_PEAK_LINE = 6, + XOM1_VALE_LINE = 7, + XOM1_FINO_UPPER_LINE = 8, + XOM1_FINO_LOWER_LINE = 9, + // 10 Ma Fast State + // 11 Ma Slow State + // 12 Sar State + XOM1_SC_HH_LINE = 13, + XOM1_SC_LL_LINE = 14, + XOM1_MC_HH_LINE = 15, + XOM1_MC_LL_LINE = 16, + XOM1_LC_HH_LINE = 17, + XOM1_LC_LL_LINE = 18, + XOM1_HC_HH_LINE = 19, + XOM1_HC_LL_LINE = 20, }; // @@ -78,13 +82,15 @@ struct XOM1Inputs double sarMax; // SAR Maximum ENUM_MA_METHOD maMethod; // MA Method ENUM_APPLIED_PRICE maAppliedTo; // MA Applied To - int maLength; // MA Length + int maFastLength; // Fast MA Length + int maSlowLength; // Slow MA Length // // Presentation ... bool showPV; // Show PV - bool showMA; // Show MA bool showSAR; // Show Sar + bool showMAFast; // Show MA Fast + bool showMASlow; // Show MA Slow bool showFiboZone; // Show Fibo Zone int startCalculationForLastBars; // Calculate Last n Bars int sarArrowCode; // Parabolic Sar Arrow Code @@ -130,13 +136,15 @@ struct XOM1Inputs sarMax = 0.2; // SAR Maximum maMethod = MODE_EMA; // MA Method maAppliedTo = PRICE_CLOSE; // MA Applied To - maLength = 10; // MA Length + maFastLength = 7; // Fast MA Length + maSlowLength = 20; // Slow MA Length // // Presentation ... showPV = true; // Show PV - showMA = true; // Show MA showSAR = true; // Show Sar + showMAFast = true; // Show MA Fast + showMASlow = true; // Show MA Slow showFiboZone = true; // Show Fibo Zone startCalculationForLastBars = 1500; // Calculate Last n Bars sarArrowCode = 159; // Parabolic Sar Arrow Code @@ -150,8 +158,9 @@ struct XOM1Inputs { // showPV = false; - showMA = false; showSAR = false; + showMAFast = false; + showMASlow = false; showFiboZone = false; } @@ -166,7 +175,9 @@ struct XOM1Inputs result = // // MA ... - maLength >= 2 && + maFastLength >= 2 && + maSlowLength >= 2 && + maSlowLength > maFastLength && // // SAR ... sarMax > 0 && @@ -203,9 +214,12 @@ struct XOM1Conditions // // Buffers ... - double maBuffer[]; - double maColorBuffer[]; - double maStateBuffer[]; + double maFastBuffer[]; + double maFastColorBuffer[]; + double maFastStateBuffer[]; + double maSlowBuffer[]; + double maSlowColorBuffer[]; + double maSlowStateBuffer[]; double sarBuffer[]; double sarColorBuffer[]; double sarStateBuffer[]; @@ -255,9 +269,12 @@ struct XOM1Conditions SpecifiedClean(bars); // - SpecifiedClean(maBuffer); - SpecifiedClean(maColorBuffer); - SpecifiedClean(maStateBuffer); + SpecifiedClean(maFastBuffer); + SpecifiedClean(maFastColorBuffer); + SpecifiedClean(maFastStateBuffer); + SpecifiedClean(maSlowBuffer); + SpecifiedClean(maSlowColorBuffer); + SpecifiedClean(maSlowStateBuffer); SpecifiedClean(sarBuffer); SpecifiedClean(sarColorBuffer); SpecifiedClean(sarStateBuffer); @@ -281,9 +298,12 @@ struct XOM1Conditions ArraySetAsSeries(bars, true); // - ArraySetAsSeries(maBuffer, true); - ArraySetAsSeries(maColorBuffer, true); - ArraySetAsSeries(maStateBuffer, true); + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); ArraySetAsSeries(sarBuffer, true); ArraySetAsSeries(sarColorBuffer, true); ArraySetAsSeries(sarStateBuffer, true); @@ -362,9 +382,12 @@ class XCXOM1Helper : public XCBaseHelper // // Buffers ... - double maBuffer[]; - double maColorBuffer[]; - double maStateBuffer[]; + double maFastBuffer[]; + double maFastColorBuffer[]; + double maFastStateBuffer[]; + double maSlowBuffer[]; + double maSlowColorBuffer[]; + double maSlowStateBuffer[]; double sarBuffer[]; double sarColorBuffer[]; double sarStateBuffer[]; @@ -420,9 +443,12 @@ class XCXOM1Helper : public XCBaseHelper } // - ArraySetAsSeries(maBuffer, true); - ArraySetAsSeries(maColorBuffer, true); - ArraySetAsSeries(maStateBuffer, true); + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); ArraySetAsSeries(sarBuffer, true); ArraySetAsSeries(sarColorBuffer, true); ArraySetAsSeries(sarStateBuffer, true); @@ -464,11 +490,13 @@ class XCXOM1Helper : public XCBaseHelper mInputs.sarMax, mInputs.maMethod, mInputs.maAppliedTo, - mInputs.maLength, + mInputs.maFastLength, + mInputs.maSlowLength, "", // Presentation ... mInputs.showPV, - mInputs.showMA, mInputs.showSAR, + mInputs.showMAFast, + mInputs.showMASlow, mInputs.showFiboZone, mInputs.startCalculationForLastBars, mInputs.sarArrowCode, @@ -588,17 +616,31 @@ class XCXOM1Helper : public XCBaseHelper // Buffers ... // - CopyMA( + CopyMAFast( zIndex, loopback, - conditions.maBuffer // + conditions.maFastBuffer // ); // - CopyMAState( + CopyMAFastState( zIndex, loopback, - conditions.maStateBuffer // + conditions.maFastStateBuffer // + ); + + // + CopyMASlow( + zIndex, + loopback, + conditions.maSlowBuffer // + ); + + // + CopyMASlowState( + zIndex, + loopback, + conditions.maSlowStateBuffer // ); // @@ -710,10 +752,10 @@ class XCXOM1Helper : public XCBaseHelper // Values Retrievers ... // - // MA ... + // Fast MA ... // - double GetMA( + double GetMAFast( int barIndex // Bar Index ) { @@ -727,18 +769,18 @@ class XCXOM1Helper : public XCBaseHelper Calculate(barIndex); // - int count = ArraySize(maBuffer); + int count = ArraySize(maFastBuffer); if (barIndex >= count) { barIndex = count - 1; } // - return maBuffer[barIndex]; + return maFastBuffer[barIndex]; } // - int CopyMA( + int CopyMAFast( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -754,7 +796,7 @@ class XCXOM1Helper : public XCBaseHelper return Copy( 0, count, - maBuffer, + maFastBuffer, buffer, forceClean // @@ -762,10 +804,10 @@ class XCXOM1Helper : public XCBaseHelper } // - // MA State ... + // Fast MA State ... // - double GetMAState( + double GetMAFastState( int barIndex // Bar Index ) { @@ -779,18 +821,18 @@ class XCXOM1Helper : public XCBaseHelper Calculate(barIndex); // - int count = ArraySize(maStateBuffer); + int count = ArraySize(maFastStateBuffer); if (barIndex >= count) { barIndex = count - 1; } // - return maStateBuffer[barIndex]; + return maFastStateBuffer[barIndex]; } // - int CopyMAState( + int CopyMAFastState( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -806,7 +848,111 @@ class XCXOM1Helper : public XCBaseHelper return Copy( 0, count, - maStateBuffer, + maFastStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow MA ... + + // + double GetMASlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maSlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maSlowBuffer[barIndex]; + } + + // + int CopyMASlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maSlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow MA State ... + + // + double GetMASlowState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(maSlowStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return maSlowStateBuffer[barIndex]; + } + + // + int CopyMASlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + maSlowStateBuffer, buffer, forceClean // @@ -1589,28 +1735,55 @@ class XCXOM1Helper : public XCBaseHelper // CopyBuffer( mHandler, - XOM1_MA_LINE, + XOM1_MA_FAST_LINE, barIndex, maxRequiredBars, - maBuffer // + maFastBuffer // ); // CopyBuffer( mHandler, - XOM1_MA_COLOR_LINE, + XOM1_MA_FAST_COLOR_LINE, barIndex, maxRequiredBars, - maColorBuffer // + maFastColorBuffer // ); // CopyBuffer( mHandler, - XOM1_MA_STATE_LINE, + XOM1_MA_FAST_STATE_LINE, barIndex, maxRequiredBars, - maStateBuffer // + maFastStateBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_SLOW_LINE, + barIndex, + maxRequiredBars, + maSlowBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_SLOW_COLOR_LINE, + barIndex, + maxRequiredBars, + maSlowColorBuffer // + ); + + // + CopyBuffer( + mHandler, + XOM1_MA_SLOW_STATE_LINE, + barIndex, + maxRequiredBars, + maSlowStateBuffer // ); // @@ -1756,19 +1929,37 @@ class XCXOM1Helper : public XCBaseHelper { // CleanupArray( - maBuffer, + maFastBuffer, maxAllowed // ); // CleanupArray( - maColorBuffer, + maFastColorBuffer, maxAllowed // ); // CleanupArray( - maStateBuffer, + maFastStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowColorBuffer, + maxAllowed // + ); + + // + CleanupArray( + maSlowStateBuffer, maxAllowed // ); diff --git a/Indicators/x-saherelm.xom1.mq5 b/Indicators/x-saherelm.xom1.mq5 index 3f1c6e16..36589db3 100644 --- a/Indicators/x-saherelm.xom1.mq5 +++ b/Indicators/x-saherelm.xom1.mq5 @@ -65,19 +65,21 @@ input ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method // // Others ... input ENUM_X_FIBO_LEVELS upperZoneLevel = X_FIBO_LEVEL_618; // Upper Zone Level -input ENUM_X_FIBO_LEVELS lowerZoneLevel = X_FIBO_LEVEL_764; // Lower Zone Level +input ENUM_X_FIBO_LEVELS lowerZoneLevel = X_FIBO_LEVEL_382; // Lower Zone Level input double sarStep = 0.02; // SAR Step input double sarMax = 0.2; // SAR Maximum input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To -input int maLength = 10; // MA Length +input int maFastLength = 7; // Fast MA Length +input int maSlowLength = 20; // Slow MA Length // // Presentation ... input group "Presentation"; input bool showPV = true; // Show PV -input bool showMA = true; // Show MA input bool showSAR = true; // Show Sar +input bool showMAFast = true; // Show MA Fast +input bool showMASlow = true; // Show MA Slow input bool showFiboZone = true; // Show Fibo Zone // @@ -112,122 +114,144 @@ input int valeArrowCode = 159; // Vales Arrow Code #property indicator_chart_window // -#property indicator_buffers 18 -#property indicator_plots 6 +#property indicator_buffers 21 +#property indicator_plots 7 // // Plot Buffers ... // -// MA ... +// Fast MA ... // -#define maBufferIndex 0 -#define maBufferPlotIndex 0 -double maBuffer[]; +#define maFastBufferIndex 0 +#define maFastBufferPlotIndex 0 +double maFastBuffer[]; // -#define maColorBufferIndex 1 -double maColorBuffer[]; +#define maFastColorBufferIndex 1 +double maFastColorBuffer[]; // -#property indicator_label1 "MA" +#property indicator_label1 "FastMA" #property indicator_type1 DRAW_COLOR_LINE -#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_color1 CLR_NONE, clrYellow, clrOrangeRed, clrGray #property indicator_width1 2 +// +// Slow MA ... + +// +#define maSlowBufferIndex 2 +#define maSlowBufferPlotIndex 1 +double maSlowBuffer[]; + +// +#define maSlowColorBufferIndex 3 +double maSlowColorBuffer[]; + +// +#property indicator_label2 "SlowMA" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width2 2 + // // SAR ... // -#define sarBufferIndex 2 -#define sarBufferPlotIndex 1 +#define sarBufferIndex 4 +#define sarBufferPlotIndex 2 double sarBuffer[]; // -#define sarColorBufferIndex 3 +#define sarColorBufferIndex 5 double sarColorBuffer[]; // -#property indicator_label2 "SAR" -#property indicator_type2 DRAW_COLOR_ARROW -#property indicator_color2 CLR_NONE, clrLime, clrRed, clrGray -#property indicator_width2 2 +#property indicator_label3 "SAR" +#property indicator_type3 DRAW_COLOR_ARROW +#property indicator_color3 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width3 2 // // PEAKS ... // -#define peakBufferIndex 4 -#define peakBufferPlotIndex 2 +#define peakBufferIndex 6 +#define peakBufferPlotIndex 3 double peakBuffer[]; // -#property indicator_label3 "PEAK" -#property indicator_type3 DRAW_ARROW -#property indicator_color3 clrMagenta -#property indicator_width3 3 +#property indicator_label4 "PEAK" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrMagenta +#property indicator_width4 3 // // VALES ... // -#define valeBufferIndex 5 -#define valeBufferPlotIndex 3 +#define valeBufferIndex 7 +#define valeBufferPlotIndex 4 double valeBuffer[]; // -#property indicator_label4 "VALE" -#property indicator_type4 DRAW_ARROW -#property indicator_color4 clrAqua -#property indicator_width4 3 +#property indicator_label5 "VALE" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrAqua +#property indicator_width5 3 // // FIBO Upper ... // -#define fiboUpperBufferIndex 6 -#define fiboUpperBufferPlotIndex 4 +#define fiboUpperBufferIndex 8 +#define fiboUpperBufferPlotIndex 5 double fiboUpperBuffer[]; // -#property indicator_label5 "FIBUP" -#property indicator_type5 DRAW_LINE -#property indicator_color5 clrAqua -#property indicator_width5 2 +#property indicator_label6 "FIBUP" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrAqua +#property indicator_width6 2 // // FIBO Lower ... // -#define fiboLowerBufferIndex 7 -#define fiboLowerBufferPlotIndex 5 +#define fiboLowerBufferIndex 9 +#define fiboLowerBufferPlotIndex 6 double fiboLowerBuffer[]; // -#property indicator_label6 "FIBLO" -#property indicator_type6 DRAW_LINE -#property indicator_color6 clrMagenta -#property indicator_width6 2 +#property indicator_label7 "FIBLO" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrMagenta +#property indicator_width7 2 // // Data Buffers ... // -#define mLastBufferIndex 7 +#define mLastBufferIndex 9 // // MA ... // -#define maStateBufferIndex mLastBufferIndex + 1 -double maStateBuffer[]; +#define maFastStateBufferIndex mLastBufferIndex + 1 +double maFastStateBuffer[]; + +// +#define maSlowStateBufferIndex mLastBufferIndex + 2 +double maSlowStateBuffer[]; // // SAR ... // -#define sarStateBufferIndex mLastBufferIndex + 2 +#define sarStateBufferIndex mLastBufferIndex + 3 double sarStateBuffer[]; // @@ -237,44 +261,44 @@ double sarStateBuffer[]; // SC ... // -#define sHHBufferIndex mLastBufferIndex + 3 +#define sHHBufferIndex mLastBufferIndex + 4 double sHHBuffer[]; // -#define sLLBufferIndex mLastBufferIndex + 4 +#define sLLBufferIndex mLastBufferIndex + 5 double sLLBuffer[]; // // MC ... // -#define mHHBufferIndex mLastBufferIndex + 5 +#define mHHBufferIndex mLastBufferIndex + 6 double mHHBuffer[]; // -#define mLLBufferIndex mLastBufferIndex + 6 +#define mLLBufferIndex mLastBufferIndex + 7 double mLLBuffer[]; // // LC ... // -#define lHHBufferIndex mLastBufferIndex + 7 +#define lHHBufferIndex mLastBufferIndex + 8 double lHHBuffer[]; // -#define lLLBufferIndex mLastBufferIndex + 8 +#define lLLBufferIndex mLastBufferIndex + 9 double lLLBuffer[]; // // HC ... // -#define hHHBufferIndex mLastBufferIndex + 9 +#define hHHBufferIndex mLastBufferIndex + 10 double hHHBuffer[]; // -#define hLLBufferIndex mLastBufferIndex + 10 +#define hLLBufferIndex mLastBufferIndex + 11 double hLLBuffer[]; // @@ -301,8 +325,9 @@ int mHCLength = 0; ENUM_TIMEFRAMES mHCPeriod = NULL; // -int maHandler = INVALID_HANDLE; int sarHandler = INVALID_HANDLE; +int maFastHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; // int limit; @@ -404,8 +429,9 @@ void OnDeinit(const int reason) // // De Initialize all Handlers and etc ... - IndicatorRelease(maHandler); IndicatorRelease(sarHandler); + IndicatorRelease(maFastHandler); + IndicatorRelease(maSlowHandler); } /** @@ -453,7 +479,8 @@ int OnCalculate( // // MA ... - int maCalculatedBars = BarsCalculated(maHandler); + int maFastCalculatedBars = BarsCalculated(maFastHandler); + int maSlowCalculatedBars = BarsCalculated(maSlowHandler); // // SAR ... @@ -463,7 +490,8 @@ int OnCalculate( bool isPassedRequiredCalculatedBars = // // MA ... - maCalculatedBars >= maxLength && + maFastCalculatedBars >= maxLength && + maSlowCalculatedBars >= maxLength && // // SAR ... sarCalculatedBars >= maxLength @@ -484,7 +512,8 @@ int OnCalculate( // // MA ... - int copiedMAs = CopyBuffer(maHandler, MAIN_LINE, 0, limit, maBuffer); + int copiedMAFasts = CopyBuffer(maFastHandler, MAIN_LINE, 0, limit, maFastBuffer); + int copiedMASlows = CopyBuffer(maSlowHandler, MAIN_LINE, 0, limit, maSlowBuffer); // // SAR ... @@ -495,7 +524,8 @@ int OnCalculate( bool isPassedRequiredCopiedItems = // // MA ... - copiedMAs >= limit && + copiedMAFasts >= limit && + copiedMASlows >= limit && // // SAR ... copiedSARs >= limit @@ -555,7 +585,9 @@ bool ValidateInputs() result = // // MA ... - maLength >= 2 && + maFastLength >= 2 && + maSlowLength >= 2 && + maSlowLength > maFastLength && // // SAR ... sarMax > 0 && @@ -588,7 +620,8 @@ int ExtractMaxLengthOfInputs() result = MathMax(mSCLength, mMCLength); result = MathMax(result, mLCLength); result = MathMax(result, mHCLength); - result = MathMax(result, maLength); + result = MathMax(result, maFastLength); + result = MathMax(result, maSlowLength); // return result; @@ -600,23 +633,42 @@ int ExtractMaxLengthOfInputs() void DefineBuffers() { // - // MA ... + // Fast MA ... // - ArraySetAsSeries(maBuffer, true); - SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + ArraySetAsSeries(maFastBuffer, true); + SetIndexBuffer(maFastBufferIndex, maFastBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(maBufferPlotIndex, PLOT_SHOW_DATA, showMA); - PlotIndexSetDouble(maBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(maFastBufferPlotIndex, PLOT_SHOW_DATA, showMAFast); + PlotIndexSetDouble(maFastBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); // - ArraySetAsSeries(maColorBuffer, true); - SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); + ArraySetAsSeries(maFastColorBuffer, true); + SetIndexBuffer(maFastColorBufferIndex, maFastColorBuffer, INDICATOR_COLOR_INDEX); // - ArraySetAsSeries(maStateBuffer, true); - SetIndexBuffer(maStateBufferIndex, maStateBuffer, INDICATOR_CALCULATIONS); + ArraySetAsSeries(maFastStateBuffer, true); + SetIndexBuffer(maFastStateBufferIndex, maFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow MA ... + + // + ArraySetAsSeries(maSlowBuffer, true); + SetIndexBuffer(maSlowBufferIndex, maSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maSlowBufferPlotIndex, PLOT_SHOW_DATA, showMASlow); + PlotIndexSetDouble(maSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(maSlowColorBuffer, true); + SetIndexBuffer(maSlowColorBufferIndex, maSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(maSlowStateBuffer, true); + SetIndexBuffer(maSlowStateBufferIndex, maSlowStateBuffer, INDICATOR_CALCULATIONS); // // SAR ... @@ -879,16 +931,32 @@ bool InitRequirements() // Handlers ... // - // MA ... - maHandler = iMA( + // Fast MA ... + maFastHandler = iMA( _Symbol, _Period, - maLength, + maFastLength, 0, maMethod, maAppliedTo // ); - result = maHandler != INVALID_HANDLE; + result = maFastHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Slow MA ... + maSlowHandler = iMA( + _Symbol, + _Period, + maSlowLength, + 0, + maMethod, + maAppliedTo // + ); + result = maSlowHandler != INVALID_HANDLE; if (!result) { return result; @@ -1053,22 +1121,40 @@ void CalculateValues( ); // - // MA ... - double iMa = maBuffer[barIndex]; - double maState = close[barIndex] > iMa - ? bullishState - : close[barIndex] < iMa - ? bearishState - : neuturalState; - double maColor = close[barIndex] > iMa - ? bullishColorIDX - : close[barIndex] < iMa - ? bearishColorIDX - : neuturalColorIDX; - maStateBuffer[barIndex] = maState; - maColorBuffer[barIndex] = showMA - ? maColor - : hideColorIDX; + // Fast MA ... + double iFastMa = maFastBuffer[barIndex]; + double maFastState = close[barIndex] > iFastMa + ? bullishState + : close[barIndex] < iFastMa + ? bearishState + : neuturalState; + double maFastColor = close[barIndex] > iFastMa + ? bullishColorIDX + : close[barIndex] < iFastMa + ? bearishColorIDX + : neuturalColorIDX; + maFastStateBuffer[barIndex] = maFastState; + maFastColorBuffer[barIndex] = showMAFast + ? maFastColor + : hideColorIDX; + + // + // Slow MA ... + double iSlowMa = maSlowBuffer[barIndex]; + double maSlowState = close[barIndex] > iSlowMa + ? bullishState + : close[barIndex] < iSlowMa + ? bearishState + : neuturalState; + double maSlowColor = close[barIndex] > iSlowMa + ? bullishColorIDX + : close[barIndex] < iSlowMa + ? bearishColorIDX + : neuturalColorIDX; + maSlowStateBuffer[barIndex] = maSlowState; + maSlowColorBuffer[barIndex] = showMASlow + ? maSlowColor + : hideColorIDX; // // SAR ... diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index 6a6a31cc..480dc2ba 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -304,6 +304,116 @@ ENUM_X_DIRECTION ToDirection(ENUM_X_POSITION_TYPES value) return result; } +// +// All Awailable Trade Restrictions ... +enum ENUM_XTRADE_RESTRICTION_PERIOD +{ + XTRADE_RESTRICATION_NONE, // None + XTRADE_RESTRICATION_HOURLY, // Per Hour + XTRADE_RESTRICATION_DAILY, // Per Day + XTRADE_RESTRICATION_WEEKLY, // Per Week + XTRADE_RESTRICATION_MONTHLY, // Per Month +}; + +// +string ToXString(ENUM_XTRADE_RESTRICTION_PERIOD value) +{ + return EnumToString(value); +} + +/** + * Check a Value Has Trade Restrictions or not ... + * + * @param value: ENUM_XTRADE_RESTRICTION_PERIOD + * Ù‘ + * @return ( bool ) + */ +bool HasRestrictions(ENUM_XTRADE_RESTRICTION_PERIOD value) +{ + return value != XTRADE_RESTRICATION_NONE; +} + +// +// All Awailable Trade Finalizations ... +enum ENUM_XTRADE_FINALIZATION +{ + XTRADE_FINAL_NONE, // None + XTRADE_FINAL_TP, // TP + XTRADE_FINAL_SL, // SL + XTRADE_FINAL_CLOSE_IN_PROFIT, // Profit + XTRADE_FINAL_CLOSE_IN_LOSE, // Lost +}; + +// +string ToXString(ENUM_XTRADE_FINALIZATION value) +{ + return EnumToString(value); +} + +// +// Position Selecting Methods ... +enum ENUM_XPOSITION_SELECT_TYPES +{ + XPOSITION_SELECT_NONE = 0, // None + XPOSITION_SELECT_ALL = 1, // All + XPOSITION_SELECT_IN_PROFITS = 2, // In Profit Positions + XPOSITION_SELECT_IN_DRAWDOWNS = 3, // In Drawdown Positions + XPOSITION_SELECT_OLDEST = 4, // Oldest Position + XPOSITION_SELECT_YOUNGEST = 5, // Youngest Position + XPOSITION_SELECT_IN_PROFITS_OLDEST = 6, // In Profit Positions Oldest one + XPOSITION_SELECT_IN_PROFITS_YOUNGEST = 7, // In Profit Positions Youngest one + XPOSITION_SELECT_IN_PROFITS_MIN = 8, // Minimum Profitable Position + XPOSITION_SELECT_IN_PROFITS_MAX = 9, // Maximum Profitable Position + XPOSITION_SELECT_IN_DRAWDOWN_OLDEST = 10, // In Drawdown Positions Oldest one + XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST = 11, // In Drawdown Positions Youngest one + XPOSITION_SELECT_IN_DRAWDOWN_MIN = 12, // Minimum in Drawdown Position + XPOSITION_SELECT_IN_DRAWDOWN_MAX = 13, // Maximum in Drawdown Position + XPOSITION_SELECT_SAMES = 14, // Same Type Positions + XPOSITION_SELECT_SAMES_OLDEST = 15, // Same Type Positions Oldest one + XPOSITION_SELECT_SAMES_YOUNGEST = 16, // Same Type Positions Youngest one + XPOSITION_SELECT_OPPOSITS = 17, // Opposit Type Positions + XPOSITION_SELECT_OPPOSIT_OLDEST = 18, // Opposit Type Positions Oldest one + XPOSITION_SELECT_OPPOSIT_YOUNGEST = 19, // Opposit Type Positions Youngest one + XPOSITION_SELECT_SAME_IN_PROFITS = 20, // Same Type In Profit Positions + XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST = 21, // Same Type In Profit Positions Oldest one + XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST = 22, // Same Type In Profit Positions Youngest one + XPOSITION_SELECT_SAME_IN_PROFITS_MIN = 23, // Minimum Profitable of Same Type Positions + XPOSITION_SELECT_SAME_IN_PROFITS_MAX = 24, // Maximum Profitable of Same Type Positions + XPOSITION_SELECT_OPPOSIT_IN_PROFITS = 25, // Opposit Type In Profit Positions + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST = 26, // Opposit Type In Profit Positions Oldest one + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST = 27, // Opposit Type In Profit Positions Youngest one + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN = 28, // Minimum Profitable of Opposit Type Positions + XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX = 29, // Maximum Profitable of Opposit Type Positions + XPOSITION_SELECT_SAME_IN_DRAWDOWNS = 30, // Same Type In Deawdown Positions + XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST = 31, // Same Type In Deawdown Positions Oldest one + XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST = 32, // Same Type In Deawdown Positions Youngest one + XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN = 33, // Minimum In Drawdown of Same Type Positions + XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX = 34, // Maximum In Drawdown of Same Type Positions + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS = 35, // Opposit Type In Deawdown Positions + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST = 36, // Opposit Type In Deawdown Positions Oldest one + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST = 37, // Opposit Type In Deawdown Positions Youngest one + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN = 38, // Minimum In Drawdown of Opposit Type Positions + XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX = 39, // Maximum In Drawdown of Opposit Type Positions +}; + +/** + * Validate Position Select Type ... + * + * @param value: ENUM_XPOSITION_SELECT_TYPES + * + * @return ( bool ) + */ +bool IsXValid(ENUM_XPOSITION_SELECT_TYPES value) +{ + return value != XPOSITION_SELECT_NONE; +} + +// +string ToXString(ENUM_XPOSITION_SELECT_TYPES value) +{ + return EnumToString(value); +} + // // Structs ... @@ -2593,201 +2703,46 @@ struct XOnTradeHandlerState }; // -struct XSymbolPositions +// an Structure for Holds an Specified Symbols +// Positions Info ... +struct XTradeSymbolInfo { // - string symbol; + // Properties ... // - double profit; - double volume; + string symbol; // Trading Symbol // - double longsProfit; - double longSupportsProfit; + int longs; // All Long Trades + int shorts; // All Short Trades // - double shortsProfit; - double shortSupportsProfit; + int trades; // All Trades // - double longsVolume; - double longSupportsVolume; + int losses; // All Loosing Trades + int profits; // All Winning Trades // - double shortsVolume; - double shortSupportsVolume; + datetime managedStart; // Managed Start Time // - double requiredProfitForHedge; + int managedSLs; // Managed SL(s) + int managedTPs; // Managed TP(s) + int managedTrades; // Managed Trades // - XPosition longs[]; - XPosition shorts[]; - XPosition supports[]; - XPosition positions[]; - XPosition longSupports[]; - XPosition shortSupports[]; + double managedBalance; // Managed Start Balance + double managedProfits; // Managed Profit(s) // - bool forceHedge; - - // - XSymbolPositions() + // Constructor ... + XTradeSymbolInfo() { Clean(); } - // - bool Update( - double mMinProfitPerTrade, - double mMinProfitPerVolumeFactor // - ) - { - // - bool result = false; - - // - bool hasChild = HasChild(); - if (!hasChild) - { - return result; - } - - // - XPosition _supports[]; - XPosition _positions[]; - - // - XPosition _tmp[]; - - // - Copy( - positions, - _tmp // - ); - - // - SpecifiedClean(positions); - - // - int tmpsCount = ArraySize(_tmp); - for (int i = 0; i < tmpsCount; i++) - { - // - XPosition iPosition = _tmp[i]; - - // - bool isSupport = IsSupport(iPosition.comment); - if (!isSupport) - { - // - AddRef( - iPosition, - _positions // - ); - } - else - { - // - AddRef( - iPosition, - _supports // - ); - } - } - - // - SpecifiedClean(_tmp); - - // - Copy( - _positions, - positions // - ); - SpecifiedClean(_positions); - - // - // Extract Types ... - ExtractPositions( - positions, - longs, - shorts // - ); - - // - Copy( - _supports, - supports // - ); - SpecifiedClean(_supports); - - // - // Extract Types ... - ExtractPositions( - supports, - longSupports, - shortSupports // - ); - - // - int numOfLongs = 0; - int numOfShorts = 0; - CountPositions( - positions, - numOfLongs, - longsProfit, - longsVolume, - numOfShorts, - shortsProfit, - shortsVolume // - ); - - // - numOfLongs = 0; - numOfShorts = 0; - CountPositions( - supports, - numOfLongs, - longSupportsProfit, - longSupportsVolume, - numOfShorts, - shortSupportsProfit, - shortSupportsVolume // - ); - - // - XPosition _allPositions[]; - Copy( - positions, - _allPositions, - false // - ); - Copy( - supports, - _allPositions, - false // - ); - - // - profit = longsProfit + shortsProfit + longSupportsProfit + shortSupportsProfit; - volume = longsVolume + shortsVolume + longSupportsVolume + shortSupportsVolume; - requiredProfitForHedge = SpecifiedCalculateRequiredProfitForHedge( - _allPositions, - mMinProfitPerTrade, - mMinProfitPerVolumeFactor // - ); - - // - SpecifiedClean(_allPositions); - - // - result = true; - - // - return result; - } - // // Tools ... @@ -2797,25 +2752,29 @@ struct XSymbolPositions { // symbol = NULL; - forceHedge = false; // - profit = 0; - longsProfit = 0; - shortsProfit = 0; + longs = 0; + shorts = 0; // - volume = 0; - longsVolume = 0; - shortsVolume = 0; + trades = 0; // - requiredProfitForHedge = 0; + losses = 0; + profits = 0; // - SpecifiedClean(longs); - SpecifiedClean(shorts); - SpecifiedClean(positions); + managedStart = NULL; + + // + managedSLs = 0; + managedTPs = 0; + managedTrades = 0; + + // + managedBalance = 0; + managedProfits = 0; // ZeroMemory(this); @@ -2836,12 +2795,118 @@ struct XSymbolPositions } // - // Has Child ... - bool HasChild() + bool IsSameAs(XTradeSymbolInfo &item) { // bool result = false; + // + result = IsValid() && + item.IsValid() && + symbol == item.symbol; + + // + return result; + } + + // + string GetRestrictionDescription( + ENUM_XTRADE_RESTRICTION_PERIOD period // + ) + { + // + string result = NULL; + + // + if (!IsValid() || + !HasRestrictions(period)) + { + return result; + } + + // + result += + "-------------------" + "\n" + + "Restrictions: " + "\n" + + "-------------------" + "\n" + + "Symbol: " + ToXString(symbol) + "\n" + + "Period: " + ToXString(period) + "\n" + + "Start: " + ToFormatString(managedStart) + "\n" + + "Balance: " + ToXString(managedBalance) + "\n" + + "-------------------" + "\n" + + "Trades: " + ToXString(managedTrades) + "\n" + + "SL: " + ToXString(managedSLs) + "\n" + + "TP: " + ToXString(managedTPs) + "\n" + + "Profit: " + ToXString(managedProfits) + "\n" + + ""; + + // + return result; + } +}; + +// +// an Structure for Describe aTrading Session ... +struct XTradeSession +{ + // + // Properties ... + string start; // Session Start Time (hh:mm) + string end; // Session End Time (hh:mm) + string name; // Session Name + + // + // Constructor ... + XTradeSession() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + end = NULL; + name = NULL; + start = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(start) && + IsSpecifiedValid(end); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Check Session is Active or Not ... + bool IsActive(datetime time = NULL) + { + // + bool result = false; + + // + time = NormalizeTime(time); + // result = IsValid(); if (!result) @@ -2850,132 +2915,104 @@ struct XSymbolPositions } // - int count = Count(); - result = IsValidSize(count); + result = IsTimeInRange( + time, + start, + end // + ); + + // + return result; + } +}; + +// +// an Structure for Describe an Specified Symbols +// Trading Sessions ... +struct XSymbolSessions +{ + // + // Propeties ... + + // + string symbol; // Trading Symbol + XTradeSession sessions[]; // Trading Sessions + + // + // Constructor ... + XSymbolSessions() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + SpecifiedClean(sessions); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol); // return result; } // - // Count ... - int Count() - { - return ArraySize(positions); - } - - // - int CountSupports() - { - return ArraySize(supports); - } - - // - int CountLongs() - { - return ArraySize(longs); - } - - // - int CountShorts() - { - return ArraySize(shorts); - } - - // - int CountLongSupports() - { - return ArraySize(longSupports); - } - - // - int CountShortSupports() - { - return ArraySize(shortSupports); - } - - // - int GetOldest( - XPosition &_oldest, // - ENUM_POSITION_TYPE _type // - ) + // Check Allow Trade in Active Sessions ... + bool CanTrade(datetime time = NULL) { // - int result = -1; + bool result = false; // - bool isLong = IsLong(_type); + // Normalize Args ... + time = NormalizeTime(time); // - int count = - isLong - ? CountLongs() - : CountShorts(); - if (!IsValidSize(count)) + // Validating ... + result = IsValid(); + if (!result) { return result; } // - if (isLong) - { - // - result = GetXOldest( - _oldest, - longs // - ); - } - else - { - // - result = GetXOldest( - _oldest, - shorts // - ); - } - - // - return result; - } - - // - int GetYoungest( - XPosition &_youngest, // - ENUM_POSITION_TYPE _type // - ) - { - // - int result = -1; - - // - bool isLong = IsLong(_type); - - // - int count = - isLong - ? CountLongs() - : CountShorts(); - if (!IsValidSize(count)) + // if there is not any defined sessions for Symbol ... + // it's allow Trading in all times ... + result = !HasChild(sessions); + if (result) { return result; } // - if (isLong) + // Detect an Active Session ... + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) { // - result = GetXYoungest( - _youngest, - longs // - ); - } - else - { - // - result = GetXYoungest( - _youngest, - shorts // - ); + result = sessions[i].IsActive(time); + if (result) + { + break; + } } // @@ -2983,222 +3020,329 @@ struct XSymbolPositions } // - int GetMaxInProfit( - XPosition &_position, - ENUM_POSITION_TYPE _type // - ) +}; + +// +// an Structure to Describe a Trade ... +struct XTradeInfo +{ + // + // Props ... + double swap; + double profit; + XSignal signal; + ulong positionID; + double commission; + string conditions; + double bullishScore; + double bearishScore; + ENUM_XTRADE_FINALIZATION finalize; + + // + datetime signaledAt; + datetime executedAt; + datetime finalizedAt; + + // + // Constructor ... + XTradeInfo() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() { // - int result = -1; + swap = 0; + profit = 0; + signal.Clean(); + commission = 0; + positionID = 0; + conditions = NULL; + bullishScore = 0; + bearishScore = 0; + finalize = XTRADE_FINAL_NONE; // - bool isLong = IsLong(_type); + signaledAt = NULL; + executedAt = NULL; + finalizedAt = NULL; // - int count = - isLong - ? CountLongs() - : CountShorts(); - if (!IsValidSize(count)) + ZeroMemory(this); + } + + /** + * Check Has Signal ... + * + * @return ( bool ) + */ + bool HasSignal() + { + // + bool result = false; + + // + result = signal.IsValid(); + + // + return result; + } + + /** + * Check Signal Executed or Not ... + * + * @return ( bool ) + */ + bool IsExecuted() + { + // + bool result = false; + + // + result = positionID > 0; + + // + return result; + } + + /** + * Check a Trade is Finalized or not ... + * + * @return ( bool ) + */ + bool IsFinalized() + { + // + bool result = false; + + // + result = HasSignal() && + IsExecuted() && + finalize != XTRADE_FINAL_NONE; + + // + return result; + } + + /** + * Generate Summary Info ... + * + * @return ( string ) + */ + string Summary() + { + // + string result = NULL; + + // + result = + // + ToXString("Swap", swap) + + ToXString("Profit", profit) + + ToXString("Commission", commission) + + ToXString("Finalize", ToXString(finalize)) + + ToXString("PositionID", positionID) + + ToXString("----------------") + "\n" + + ToXString("Signaled At", ToFormatString(signaledAt)) + + ToXString("Executed At", ToFormatString(executedAt)) + + ToXString("Finalized At", ToFormatString(finalizedAt)) + // + ; + + // + return result; + } + + /** + * Get Data Collection File Name ... + * + * @return ( string ) + */ + string GetFileName() + { + // + string result = NULL; + + // + bool hasSignal = HasSignal(); + bool isExecuted = IsExecuted(); + bool isFinalized = IsFinalized(); + if (!hasSignal && !isExecuted && !isFinalized) { return result; } // - if (isLong) - { + result = // - result = FindMaxProfitIndex( - longs // - ); - + signal.symbol + "\\" + + ToString(signal.type) + "\\" + + (profit >= 0 ? "Profit" : "Loss") + "\\" + + ToString(positionID) + "_" + + ToString(signal.period) + "_" + + ToFormatString(signaledAt) // - if (IsValidIndex(result)) - { - _position = longs[result]; - } - } - else - { - // - result = FindMaxProfitIndex( - shorts // - ); - - // - if (IsValidIndex(result)) - { - _position = shorts[result]; - } - } + ; // return result; } - // - int GetMinInProfit( - XPosition &_position, - ENUM_POSITION_TYPE _type // + /** + * Converts Model to String Representation ... + * + * @param onlySignals: Boolean, Specified Represent Only Signal or not ... + * + * @return ( string ) + */ + string ToString( + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // ) { // - int result = -1; + string result = NULL; // - bool isLong = IsLong(_type); + // Generating Model Summary ... + string summary = Summary(); // - int count = - isLong - ? CountLongs() - : CountShorts(); - if (!IsValidSize(count)) + // Generating Signal Summary ... + string signalSummary = signal.ToString(); + + // + if (includeSummary) { - return result; + // + result += + ToXString("----------------") + "\n" + + ToXString("Summary: ") + "\n" + + ToXString("----------------") + "\n" + + summary + "\n"; } // - if (isLong) + if (includeSignal) { // - result = FindMinProfitIndex( - longs // - ); - - // - if (IsValidIndex(result)) - { - _position = longs[result]; - } + result += + ToXString("----------------") + "\n" + + ToXString("Signal: ") + "\n" + + ToXString("----------------") + "\n" + + signalSummary + "\n"; } - else + + // + if (includeConditions) { // - result = FindMinProfitIndex( - shorts // - ); - - // - if (IsValidIndex(result)) - { - _position = shorts[result]; - } + result += + ToXString("----------------") + "\n" + + ToXString("Conditions: ") + "\n" + + ToXString("----------------") + "\n" + + conditions + "\n"; } // return result; } - // - int GetMaxInDrawdown( - XPosition &_position, - ENUM_POSITION_TYPE _type // - ) + string GetConditionsString() { // - int result = -1; + string result = NULL; // - bool isLong = IsLong(_type); - - // - int count = - isLong - ? CountLongs() - : CountShorts(); - if (!IsValidSize(count)) - { - return result; - } - - // - if (isLong) + string conditionsStr = + conditions; + string condParts[]; + int condPartsCount = SplitContent( + condParts, + conditionsStr, + "\n" // + ); + if (IsValidSize(condPartsCount)) { // - result = FindMaxDrawdownIndex( - longs // - ); - - // - if (IsValidIndex(result)) + conditionsStr = NULL; + while (HasChild(condParts)) { - _position = longs[result]; + // + string iStr = condParts[0]; + ArrayRemove( + condParts, + 0, + 1 // + ); + + // + bool isLast = !HasChild(condParts); + + // + bool isCond = Contains( + "is", + iStr, + false // + ); + if (isCond) + { + // + string iParts[]; + int iPartsCount = SplitContent( + iParts, + iStr, + ":" // + ); + if (iPartsCount == 2) + { + // + string iVal = iParts[1]; + StringTrimLeft(iVal); + StringTrimRight(iVal); + bool isPassed = ToBoolean(iVal); + conditionsStr += (isPassed ? "" : "!") + "conditions." + iParts[0] + (!isLast ? " &&" : "") + "\n"; + } + } } + SpecifiedClean(condParts); } else { - // - result = FindMaxDrawdownIndex( - shorts // - ); - - // - if (IsValidIndex(result)) - { - _position = shorts[result]; - } + conditionsStr = NULL; } + // + result = + "(" + "\n" + + "\\" + "\\" + " " + ToXString("Type", ToXString(signal.type)) + + "\\" + "\\" + " " + ToXString("Profit", profit) + + "\\" + "\\" + " " + ToXString("Finalize", ToXString(finalize)) + + "\\" + "\\" + " " + ToXString("PositionID", positionID) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + "\\" + "\\" + " " + ToXString("Signaled At", ToFormatString(signaledAt)) + + "\\" + "\\" + " " + ToXString("Executed At", ToFormatString(executedAt)) + + "\\" + "\\" + " " + ToXString("Finalized At", ToFormatString(finalizedAt)) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + "\\" + "\\" + " " + ToXString("Scores:") + "\n" + + "\\" + "\\" + " " + ToXString("Bullish", bullishScore) + + "\\" + "\\" + " " + ToXString("Bearish", bearishScore) + + "\\" + "\\" + " " + ToXString("----------------") + "\n" + + conditionsStr + + (IsValid(conditionsStr) ? "" : "") + + ") && "; + // return result; } - - // - int GetMinInDrawdown( - XPosition &_position, - ENUM_POSITION_TYPE _type // - ) - { - // - int result = -1; - - // - bool isLong = IsLong(_type); - - // - int count = - isLong - ? CountLongs() - : CountShorts(); - if (!IsValidSize(count)) - { - return result; - } - - // - if (isLong) - { - // - result = FindMinDrawdownIndex( - longs // - ); - - // - if (IsValidIndex(result)) - { - _position = longs[result]; - } - } - else - { - // - result = FindMinDrawdownIndex( - shorts // - ); - - // - if (IsValidIndex(result)) - { - _position = shorts[result]; - } - } - - // - return result; - } - - // }; // @@ -5061,126 +5205,6 @@ void ExtractPositions( } } -// -int FindSymbolIndex( - string mSymbol, - XSymbolPositions &mItems[] // -) -{ - // - int result = -1; - - // - if (!IsValid(mSymbol)) - { - return result; - } - - // - int count = ArraySize(mItems); - if (!IsValidSize(count)) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - XSymbolPositions iItem = mItems[i]; - - // - if (iItem.symbol == mSymbol) - { - // - result = i; - break; - } - } - - // - return result; -} - -// -int ExtractSymbolPositions( - XPosition &positions[], - XSymbolPositions &items[], // Holds Result - double mMinProfitPerTrade, - double mMinProfitPerVolumeFactor // -) -{ - // - int result = 0; - - // - int positionsCount = ArraySize(positions); - if (!IsValidSize(positionsCount)) - { - return result; - } - - // - Clean(items); - - // - for (int i = 0; i < positionsCount; i++) - { - // - XPosition iPosition = positions[i]; - - // - if (!iPosition.IsValid()) - { - continue; - } - - // - int itemIDX = FindSymbolIndex( - iPosition.symbol, - items // - ); - if (!IsValidIndex(itemIDX)) - { - // - // Add New One ... - XSymbolPositions item; - item.symbol = iPosition.symbol; - - // - AddRef( - item, - items // - ); - itemIDX = FindSymbolIndex(iPosition.symbol, items); - } - - // - AddRef( - iPosition, - items[itemIDX].positions // - ); - } - - // - result = ArraySize(items); - if (IsValidSize(result)) - { - // - for (int i = 0; i < result; i++) - { - // - items[i].Update( - mMinProfitPerTrade, - mMinProfitPerVolumeFactor // - ); - } - } - - // - return result; -} - // // Apply a Collection of Targets // on Specified Signal ... @@ -5213,4 +5237,800 @@ void ApplyTargetsOnSignal( ); } +/** + * Select Specified Position's Related Position(s) + * for Protecting ... + * + * @param selecteds: XPosition instance reference Collection, for Holding Selected Positions ... + * @param positions: XPosition instance reference Collection, All available source Positions ... + * @param forType: ENUM_X_POSITION_TYPES member, Spcified Position Type to Select for it ... + * @param selectType: ENUM_XPOSITION_SELECT_TYPES member, Specified Positions Selecting Senario ... + * + * @return ( bool ) + */ +bool SelectPosition( + XPosition &selecteds[], + XPosition &positions[], + ENUM_X_POSITION_TYPES forType, + ENUM_XPOSITION_SELECT_TYPES selectType // +) +{ + // + bool result = false; + + // + // Normalize Args ... + Clean(selecteds); + + // + // Validate Args ... + result = + IsValid(forType) && + HasChild(positions) && + IsXValid(selectType); + if (!result) + { + return result; + } + + // + // Extract Separate Type of Positions ... + + // + int idx = -1; + bool has = false; + XPosition iPosition; + + // + bool isLong = IsLong(forType); + bool isShort = IsShort(forType); + int count = ArraySize(positions); + + // + XPosition samePositions[]; + XPosition oppositPositions[]; + XPosition inProfitPositions[]; + XPosition inDrawdownPositions[]; + XPosition sameInProfitPositions[]; + XPosition sameInDrawdownPositions[]; + XPosition oppositInProfitPositions[]; + XPosition oppositInDrawdownPositions[]; + + // + for (int i = 0; i < count; i++) + { + // + // Select Indexed Position ... + iPosition = positions[i]; + + // + bool isIPosLong = IsLong(iPosition.type); + bool isIPosShort = IsShort(iPosition.type); + + // + // Select if Same Type ... + bool isSame = + (isLong && isIPosLong) || + (isShort && isIPosShort); + if (isSame) + { + // + AddRef( + iPosition, + samePositions // + ); + } + + // + // Select if Opposit Type ... + bool isOpposit = + (isLong && isIPosShort) || + (isShort && isIPosLong); + if (isOpposit) + { + // + AddRef( + iPosition, + oppositPositions // + ); + } + + // + iPosition.Clean(); + } + + // + // Filling Other Requirement Collections ... + + // + ExtractInProfitPositions( + positions, + inProfitPositions // + ); + + // + ExtractInProfitPositions( + samePositions, + sameInProfitPositions // + ); + + // + ExtractInProfitPositions( + oppositPositions, + oppositInProfitPositions // + ); + + // + ExtractInDrawdownPositions( + positions, + inDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + samePositions, + sameInDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + oppositPositions, + oppositInDrawdownPositions // + ); + + // + // Implement Selection Senario ... + switch (selectType) + { + // + case XPOSITION_SELECT_ALL: + // + Copy( + positions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_IN_PROFITS: + // + Copy( + inProfitPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWNS: + // + Copy( + inDrawdownPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OLDEST: + // + GetOldest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_YOUNGEST: + // + GetYoungest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAMES: + // + Copy( + samePositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_SAMES_OLDEST: + // + GetOldest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAMES_YOUNGEST: + // + GetYoungest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS: + // + Copy( + oppositPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OPPOSIT_OLDEST: + // + GetOldest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_YOUNGEST: + // + GetYoungest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS: + // + Copy( + sameInProfitPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS: + // + Copy( + oppositInProfitPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWNS: + // + Copy( + sameInDrawdownPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS: + // + Copy( + oppositInDrawdownPositions, + selecteds // + ); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + } + + // + // Validate Result ... + result = HasChild(selecteds); + + // + // Cleanup Resources ... + + // + if (!result) + { + Clean(selecteds); + } + + // + Clean(samePositions); + Clean(oppositPositions); + Clean(inProfitPositions); + Clean(inDrawdownPositions); + Clean(sameInProfitPositions); + Clean(sameInDrawdownPositions); + Clean(oppositInProfitPositions); + Clean(oppositInDrawdownPositions); + + // + return result; +} + // \ No newline at end of file diff --git a/XOM1EA/Classes/xom1ea.expert.class.mq5 b/XOM1EA/Classes/xom1ea.expert.class.mq5 index 8edca790..ec530a73 100644 --- a/XOM1EA/Classes/xom1ea.expert.class.mq5 +++ b/XOM1EA/Classes/xom1ea.expert.class.mq5 @@ -24,6 +24,8 @@ // Imports ... #include "../../Classes/x-saherelm.base.class.mq5" #include "../../Classes/x-saherelm.x-alert.class.mq5" +#include "../../Classes/x-saherelm.x-guard.class.mq5" +#include "../../Classes/x-saherelm.x-trade-manager.class.mq5" #include "../../Classes/x-saherelm.x-volume.class.mq5" #include "../Classes/xom1ea.signaller.class.mq5" @@ -46,6 +48,22 @@ class XCXOM1EAExpert : public XCBase int eaSlippage; // Slippgae string eaLogSuffix; // Log Suffix + // + // Management ... + bool eaAllowGuards; // Allow Guards + bool eaAllowTrade; // Allow Trade on Signals + bool eaAllowLongs; // Allow Long Trades + bool eaAllowShorts; // Allow Short Trades + string eaSessions; // Active Sessions + ENUM_XTRADE_RESTRICTION_PERIOD eaRestrictionsPeriod; // Restrictions Period + int eaMaxAllowedTPs; // Max Allowed TP(s) in Restrictions Period + int eaMaxAllowedSLs; // Max Allowed SL(s) in Restrictions Period + int eaMaxAllowedTrades; // Max Allowed Trades in Restrictions Period + int eaMaxAllowedPositions; // Max Allowed Same Time Trades + double eaMaxAllowedSpread; // Max Allowed Spread For Trade + double eaMaxAllowedDrawdownFactor; // Max Allowed DrawDown for Trade + string eaCloseAllOpenTradesAt; // Close All Open Trades per Day At Specified Time + // // Volume ... ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect; // Volume Applying Type @@ -65,12 +83,195 @@ class XCXOM1EAExpert : public XCBase bool eaPushAlerts; // Push Alerts bool eaTerminalAlerts; // Terminal Alerts + // + // Reports ... + bool eaReportNewMonths; // Report New Month + bool eaReportNewWeeks; // Report New Weeks + bool eaReportNewDays; // Report New Days + bool eaReportNewHours; // Report New Hours + bool eaReportTrades; // Report Trades + bool eaReportSignals; // Report Signals + bool eaReportProtector; // Report Protector Actions + bool eaReportRestrictions; // Report Restrictions + bool eaReportAfterTradesBalance; // Report Balance after a Trade Finished + + // + // Collector ... + bool eaSaveTrades; // Save Trades + bool eaSaveSignals; // Save Signals + bool eaSaveWins; // Save Winning Conditions + bool eaSaveLosts; // Save Lost Conditions + bool eaSaveRestrictions; // Save Restriction Reports + // // Requirements ... // - XCAlert *eaAlert; // EA Scope Alert Handler ... - XCVolume *eaVolume; // EA Scope Voluem Handler ... + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCTrade *eaTrade; // EA Scope Trade Handler ... + XCTradeManager *eaTradeManager; // EA Scope Trade Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + + // + // Tools / Actions / Handlers ... + + // + // Trade Event Handlers ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } // // Validators ... @@ -114,6 +315,10 @@ class XCXOM1EAExpert : public XCBase return result; } + // + int count = 0; + bool has = false; + // // Initialize Alert Handler ... eaAlert = new XCAlert(); @@ -127,20 +332,209 @@ class XCXOM1EAExpert : public XCBase // // Initialize Volume Manager ... - // eaVolume = new XCVolume(); - // result = eaVolume.Init( - // eaVolumeSelect, - // eaStaticVoluem, - // eaDynamicVolumeStepBalance, - // eaDynamicVolumeStepVolume, - // eaConstantRiskBalance, - // eaConstantPercent, - // eaConstantBalance // - // ); - // if (!result) - // { - // return result; - // } + eaVolume = new XCVolume(); + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + if (!result) + { + return result; + } + + // + // Initialize Trader ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + eaMaxAllowedSpread, + eaMaxAllowedPositions, + eaMaxAllowedDrawdownFactor // + ); + + // + // Trade Handler Attachments ... + + // + // Position Modifiy Event Handlers ... + count = ArraySize(mOnModifyEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnModifyPositionEventHandler(mOnModifyEventHandlers[i]); + } + } + + // + // Position Stop Loss Event Handlers ... + count = ArraySize(mStopLossEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnStopLossEventHandler(mStopLossEventHandlers[i]); + } + } + + // + // Position Take Profit Event Handlers ... + count = ArraySize(mTakeProfitEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTakeProfitEventHandler(mTakeProfitEventHandlers[i]); + } + } + + // + // Position Force Close Event Handlers ... + count = ArraySize(mOnForceCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnForceClosePositionEventHandler(mOnForceCloseEventHandlers[i]); + } + } + + // + // Deals Changed Event Handlers ... + count = ArraySize(mDealsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnDealsChangedEventHandler(mDealsChangedEventHandlers[i]); + } + } + + // + // Orders Changed Event Handlers ... + count = ArraySize(mOrdersChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnOrdersChangedEventHandler(mOrdersChangedEventHandlers[i]); + } + } + + // + // Positions Changed Event Handlers ... + count = ArraySize(mPositionsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPositionsChangedEventHandler(mPositionsChangedEventHandlers[i]); + } + } + + // + // Trade Changed Event Handlers ... + count = ArraySize(mTradeStateChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTradeStateChangedEventHandler(mTradeStateChangedEventHandlers[i]); + } + } + + // + // Postion Partially Close Event Handlers ... + count = ArraySize(mOnPartialCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPartialClosePositionEventHandler(mOnPartialCloseEventHandlers[i]); + } + } + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrade // + ); + + // + // Initialize Trae Manager ... + eaTradeManager = new XCTradeManager( + eaAlert, + eaTrade, + eaGuard // + ); + + // + // Configuring Trade Manager ... + + // + eaTradeManager.SaveWins(eaSaveWins); + eaTradeManager.SaveLosts(eaSaveLosts); + eaTradeManager.SaveTrades(eaSaveTrades); + eaTradeManager.SaveSignals(eaSaveSignals); + eaTradeManager.SaveRestrictions(eaSaveRestrictions); + + // + // Enable Force Close At ... + eaTradeManager.SetForceCloseTradesAt(eaCloseAllOpenTradesAt); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportRestrictions, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // Setting Trade Restrictions ... + eaTradeManager + .SetTradeRestrictions( + eaRestrictionsPeriod, + eaMaxAllowedTPs, + eaMaxAllowedSLs, + eaMaxAllowedTrades // + ); // // Here we Apply Symbols,Periods and Configs ... @@ -171,7 +565,7 @@ class XCXOM1EAExpert : public XCBase // Register Signaller ... Add( iDZoneSignaller, - signallers // + eaSignallers // ); } @@ -192,10 +586,28 @@ class XCXOM1EAExpert : public XCBase { // + // + delete eaTrade; + ZeroMemory(eaTrade); + + // + delete eaGuard; + ZeroMemory(eaGuard); + // delete eaVolume; ZeroMemory(eaVolume); + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + eaTimeTracker.Clean(); + + // + Clean(eaSignallers); + // string message = "DeInitialized Successfully ..."; eaAlert.SendAlert(message); @@ -211,7 +623,7 @@ class XCXOM1EAExpert : public XCBase void HandleOnTick() { // - int count = ArraySize(signallers); + int count = ArraySize(eaSignallers); bool has = IsValidSize(count); if (!has) { @@ -224,7 +636,7 @@ class XCXOM1EAExpert : public XCBase { // // Calling Process Ticks on Signaller ... - signallers[i].ProcessTick(0); + eaSignallers[i].ProcessTick(0); } } @@ -262,9 +674,185 @@ class XCXOM1EAExpert : public XCBase // // Trade Event Handlers ... + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + eaTradeManager.HandleSL(deal); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + eaTradeManager.HandleTP(deal); + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + eaTradeManager.HandleForceClose(position); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + eaTradeManager.HandlePartiallyClosed( + ticket, + profit, + comment // + ); + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + // // Protected ... protected: + // + + /** + * Report Time Changes based on Given Configurations ... + */ + void HandleTimeReport() + { + // + if (eaAlert == NULL) + { + return; + } + + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } + } + // // Private ... private: @@ -272,7 +860,18 @@ class XCXOM1EAExpert : public XCBase // Props ... // - XCXOM1SignallerBase *signallers[]; // All Registered Signallers ... + TOnModify mOnModifyEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnDealsChanged mDealsChangedEventHandlers[]; + TOnOrdersChanged mOrdersChangedEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + TOnPositionsChanged mPositionsChangedEventHandlers[]; + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + XCXOM1SignallerBase *eaSignallers[]; // All Registered Signallers ... }; // diff --git a/XOM1EA/Classes/xom1ea.x-trade.manager.class.mq5 b/XOM1EA/Classes/xom1ea.x-trade.manager.class.mq5 deleted file mode 100644 index e69de29b..00000000