/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // ---------------------------------------------- // Name: XSCBaseEA // Description: provides all Base EA 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 // // START Definitions ... // // // END Definitions ... // // // START Import and Inclused requirements ... // // // Includes ... #include "../Libraries/x-saherelm.alert.lib.mq5" #include "../Libraries/x-saherelm.common.lib.mq5" #include "../Classes/x-saherelm.xtrade.class.mq5" #include "../Classes/x-saherelm.xaccount.class.mq5" #include "../Classes/x-saherelm.xprovider.class.mq5" #include "../Libraries/x-saherelm.seriallizer.lib.mq5" // // END Import and Inclused requirements ... // // // START Overrides ... // // // END Overrides ... // // // a Class for Handle base requirements ... // for indicators ... class XSCBaseEA { // // Public ... public: // // Props ... XSCTrade *mTrader; XSCAccount *mAccount; // bool isNewHour; bool isNewDay; bool isNewWeek; bool isNewMonth; bool isNewCandle; // bool isInTestMode; // bool mWaitsUntilNewCandle; // // Constructor ... void XSCBaseEA( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Time Frame ulong magic, // Magic Number int slippage, // Slippgae TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler TOnTradeStateChanged onTradeStateChangedHandler = NULL // On Trade State Changed Event Handler ) { // mSymbol = symbol; mPeriod = period; // mMagic = magic; mSlippage = slippage; // mOnStopLossTriggered = onStopLossTriggered; mOnTakeProfitTriggered = onTakeProfitTriggered; mOnDealsChangedHandler = onDealsChangedHandler; mOnOrdersChangedHandler = onOrdersChangedHandler; mOnPositionsChangedHandler = onPositionsChangedHandler; mOnTradeStateChangedHandler = onTradeStateChangedHandler; // // Reset Timings ... ResetTiming(); // EnableLongs(true); EnableShorts(true); // MaxAllowedPositions(0); MaxAllowedDrawDownFactor(0); // InitRequirements(); } // // Deconstructor ... void ~XSCBaseEA() { // delete mTrader; delete mAccount; } // // START Properties ... // // // Symbol ... string GetSymbol() { return mSymbol; } // // Period ... ENUM_TIMEFRAMES GetPeriod() { return mPeriod; } // // Tag ... string GetTag() { return mTag; } // ulong GetMagic() { return mMagic; } // int GetSlippage() { return mSlippage; } // // Check Long Signalling State ... bool EnableLongs() { return mEnableLongs; } // // Set Long Signalling State ... void EnableLongs(bool enable) { // if (enable == mEnableLongs) { return; } // mEnableLongs = enable; } // // Check Short Signalling State ... bool EnableShorts() { return mEnableShorts; } // // Set Short Signalling State ... void EnableShorts(bool enable) { // if (enable == mEnableShorts) { return; } // mEnableShorts = enable; } // // Get Max Allowed Positions at Same Time ... int MaxAllowedPositions() { return mMaxAllowedPositions; } // // Set Max Allowed Positions at Same Time ... void MaxAllowedPositions(int value) { // if (value < 0 || value == mMaxAllowedPositions) { return; } // mMaxAllowedPositions = value; } // // Get Max Allowed DrawDown Factor ... double MaxAllowedDrawDownFactor() { return mMaxAllowedDrawDownFactor; } // // Set Max Allowed Positions at Same Time ... void MaxAllowedDrawDownFactor(double value) { // if (value < 0 || value == mMaxAllowedDrawDownFactor) { return; } // mMaxAllowedDrawDownFactor = value; } // // Check Acocunt Balance is Allow new Trades or not ... bool CheckEquityForTrade() { // bool result = false; // if (mMaxAllowedDrawDownFactor <= 0) { // result = true; return result; } // double equity = mAccount.GetEquity(); double balance = mAccount.GetBalance(); // double selectedBalance = MathMax(equity, balance) - MathMin(equity, balance); // double balanceForFactor = MathAbs(equity - balance); if (balanceForFactor <= 0) { balanceForFactor = balance; } else { balanceForFactor = equity; } // double maxAllowedBalanceDrawDown = balanceForFactor * mMaxAllowedDrawDownFactor; // result = equity > balance || (equity <= balance && selectedBalance <= maxAllowedBalanceDrawDown); // return result; } // // Check Max Allowed Positions Policy for Trade ... bool ChecPositionsForTrade() { // bool result = false; // if (mMaxAllowedPositions <= 0) { // result = true; return result; } // int positionsCount = mTrader.CountPositions(); if (positionsCount <= 0) { // result = true; return result; } // result = positionsCount <= mMaxAllowedPositions; // return result; } // // Check Account Policies ... bool CheckAccountPolicies() { // bool result = false; // // Check Equity for Trade ... result = CheckEquityForTrade(); if (!result) { // string message = "not enough Equity for Trade ..."; // LogMessage(message); // // // // Handle Force Close Positions on Max Drawdown ... // HandleGuardForceCloseAction( // NULL, // All Providers ... // NULL, // All Symbols ... // NULL, // All Type of Positions ... // NULL // All Periods ... // ); // return result; } // // Check Max Allowed Position for Trade ... result = ChecPositionsForTrade(); if (!result) { // string message = "max allowed Positions reached ..."; // LogMessage(message); // // // HandleGuardCloseInProfitAction( // NULL, // All Providers ... // NULL, // All Symbols ... // NULL, // All Type of Positions ... // NULL, // All Periods ... // X_POSITION_SELECT_MAX // Select Max Position ... // ); // // // HandleGuardCloseInDrawdownAction( // NULL, // All Providers ... // NULL, // All Symbols ... // NULL, // All Type of Positions ... // NULL, // All Periods ... // X_POSITION_SELECT_MAX // Select Max Position ... // ); // return result; } // return result; } // // END Properties ... // // // START Provided Functions ... // // // Prepare Tag ... virtual void PrepareTag() { mTag = "XEA" + mSymbol + "," + ToString(mPeriod) + (string)mMagic; } // // Handle Chart Events ... virtual void OnChartEvent( const int id, // event ID const long &lparam, // long type event parameter const double &dparam, // double type event parameter const string &sparam // string type event parameter ) { } // // Check any Registered Providers Signalling ... virtual bool SignalCheck(XSignal &signals[]) { return false; } // // Check for any Custom Guard Actions Guard Actions ... virtual bool CheckGuard(XGuard &guards[]) { return false; } // // NOTE: you have to call these Functions on Static Classes to Handle Works ... // // Handle StopLoss Event ... virtual void OnStopLossTriggered(const XDeal &deal) {} // // Handle TakeProfit Event ... virtual void OnTakeProfitTriggered(const XDeal &deal) {} // // Handle Deals Changed Event ... virtual void OnDealsChangedHandler(int count) {} // // Handle Order Changed Event ... virtual void OnOrdersChangedHandler(int count) {} // // Handle Position Changed Event ... virtual void OnPositionsChangedHandler(int count) {} // // Handle Trade State Changed ... virtual void OnTradeStateChangedHandler(const XOnTradeHandlerState &state) {} // // Implemented Actions ... // // OnTick Handler ... void OnTick() { // // Check Account Policies ... bool isAccountPassed = CheckAccountPolicies(); if (!isAccountPassed) { return; } // // First Check Guards .... // Only when Open Positions Exists or Has Pending Order ... XGuard guards[]; bool hasGuard = CheckGuard(guards); if (hasGuard) { DoGuards(guards); } // XSignal signals[]; bool hasSignal = SignalCheck(signals); if (hasSignal) { // // Here we have to Check Signals and also it's State ... XSignal enabledSignals[]; int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return; } // // Filter Signals by their type and // also Check EA Enable their type ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; bool isLong = IsLong(iSignal.type); if ((isLong && mEnableLongs) || (!isLong && mEnableShorts)) { // PrepareSignal(iSignal); // Add( iSignal, enabledSignals); } } // int enabledSignalsCount = ArraySize(enabledSignals); if (enabledSignalsCount <= 0) { return; } // // Check Trade Policies ... // // Check Equity for Trade ... bool canDoTrade = CheckEquityForTrade(); if (!canDoTrade) { // string message = "not enough Equity for Trade ..."; // LogMessage(message); return; } // // Check Max Allowed Position for Trade ... canDoTrade = ChecPositionsForTrade(); if (!canDoTrade) { // string message = "max allowed Positions reached ..."; // LogMessage(message); // // Check How to Act with Signals if Max In Drawdown Reached ... // TODO: Here we Have to Define Max In Draw Down Position type ... return; } // mTrader.ExecuteSignals(enabledSignals); } } // // Handle On Trade ... void OnTrade() { // XOnTradeHandlerState state = mTrader.HandleOnTrade(); // if ( !state.hasNewDeal && !state.hasNewOrder && !state.hasNewPosition && !state.hasNewHistoryOrder) { return; } // // STATE ... // // Notfy Trade State Changed Event ... OnTradeStateChangedHandler(state); // // DEALS ... if (state.hasNewDeal) { // // Notfy Deals Changed Event ... OnDealsChangedHandler(state.newDeals); // // Retrieve Last Deal ... XDeal deals[]; mTrader.GetDeals(deals); int dealsCount = ArraySize(deals); if (dealsCount > 0) { // XDeal lastDeal = deals[0]; // if (lastDeal.reason == DEAL_REASON_TP) { OnTakeProfitTriggered(lastDeal); } else if (lastDeal.reason == DEAL_REASON_SL) { OnStopLossTriggered(lastDeal); } } } // // ORDERS ... if (state.hasNewOrder || state.hasNewHistoryOrder) { // // Notfy Orders Changed Event ... OnOrdersChangedHandler(state.newOrders + state.newHistoryOrders); } // // POSITIONS ... if (state.hasNewPosition) { // // Notfy Positions Changed Event ... OnPositionsChangedHandler(state.newPositions); } } // // Retrieve Dept Of Market ... void OnBookEvent(const string &symbol) { // // TODO: Implement this ... } // // TOOLS ... // // Prepare a Signal and Do Calculations ... void PrepareSignal( XSignal &signal // a Signal for Preparation ... ) { // // Calculate Volume ... if (signal.useRiskAmountAsVolume && signal.riskAmount > 0) { signal.volume = signal.riskAmount; } else if ( signal.sl > 0 && signal.tp > 0 && signal.volume == 0 && signal.riskAmount > 0 && !signal.useSupportAndResistance) { // // Calculate Risk Point ... double riskPoint = MathAbs(signal.entry - signal.sl); riskPoint = PriceToPoint( signal.symbol, riskPoint); // double volume = mAccount.CalculateVolume( signal.symbol, signal.riskAmount, riskPoint); // signal.volume = volume; } else if (signal.useSupportAndResistance) { // // Calculate Everything using Supports and Resistances ... // TODO: Implement Later ... } // if (signal.ignoreTP) { signal.tp = 0; } // if (signal.ignoreSL) { signal.sl = 0; } // // Normalize Signal ... NormalizeSignal(signal); } // // Get All Open Trades ... void GetPositions( XPosition &result[], // Hold Result ... string symbol = NULL, // Trading Symbol ... ENUM_POSITION_TYPE type = NULL, // Trading Type ... ENUM_TIMEFRAMES period = NULL, // Trading Period ... string provider = NULL // Signal Provider ... ) { // Clean(result); // bool hasSymbol = !(symbol == NULL || StringLen(symbol) == 0); bool hasProvider = !(provider == NULL || StringLen(provider) == 0); // int positionsCount = mTrader.CountPositions(); if (positionsCount <= 0) { return; } // XPosition positions[]; mTrader.GetPositions( positions, symbol, period); positionsCount = ArraySize(positions); if (positionsCount <= 0) { return; } // if (!hasProvider && type == NULL) { // Copy( positions, result); // return; } // if (type == NULL) { // ArrayResize( result, ArraySize(positions)); // for (int i = 0; i < positionsCount; i++) { // Add( positions[i], result); } // return; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // string iProvider = ExtractProvider(iPosition.comment); if (hasProvider && iProvider != provider) { continue; } // if (type == NULL || iPosition.type == type) { // Add( iPosition, result); } } } // // Get All In Profit Trades ... void GetInProfitPositions( XPosition &result[], // Hold Result ... string symbol = NULL, // Trading Symbol ... ENUM_POSITION_TYPE type = NULL, // Trading Type ... ENUM_TIMEFRAMES period = NULL, // Trading Period ... string provider = NULL, // Signal Provider ... ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method ... ) { // Clean(result); // if (method == NULL) { method = X_POSITION_SELECT_ALL; } // // Prevent Going Forwars Since selection type is NONE ... if (method == X_POSITION_SELECT_NONE) { return; } // bool isMinSelectable = method == X_POSITION_SELECT_MIN; bool isMaxSelectable = method == X_POSITION_SELECT_MAX; // XPosition positions[]; GetPositions( positions, symbol, type, period, provider); int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return; } // // Define Temp Position for Selecting Max Position ... XPosition maxPos; maxPos.profit = INVALID_HANDLE; // // Define Temp Position for Selecting Min Position ... XPosition minPos; minPos.profit = INVALID_HANDLE; // // Loop through available Positions for Selecting Positions ... for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // // Check Profit State ... if (iPosition.profit <= 0) { continue; } // // Check Selection State ... if (isMinSelectable) { // if (minPos.profit == INVALID_HANDLE || minPos.profit > iPosition.profit) { minPos = iPosition; } // continue; } else if (isMaxSelectable) { // if (maxPos.profit == INVALID_HANDLE || maxPos.profit < iPosition.profit) { maxPos = iPosition; } // continue; } else { // Add( iPosition, result); } } // // Add Selected Position if Provided to Results ... if (isMinSelectable) { // Add( minPos, result); } else if (isMaxSelectable) { // Add( maxPos, result); } } // // Get All In Drawdown Trades ... void GetInDrawdownPositions( XPosition &result[], // Hold Result ... string symbol = NULL, // Trading Symbol ... ENUM_POSITION_TYPE type = NULL, // Trading Type ... ENUM_TIMEFRAMES period = NULL, // Trading Period ... string provider = NULL, // Signal Provider ... ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method ... ) { // Clean(result); // if (method == NULL) { method = X_POSITION_SELECT_ALL; } // // Prevent Going Forwars Since selection type is NONE ... if (method == X_POSITION_SELECT_NONE) { return; } // bool isMinSelectable = method == X_POSITION_SELECT_MIN; bool isMaxSelectable = method == X_POSITION_SELECT_MAX; // XPosition positions[]; GetPositions( positions, symbol, type, period, provider); int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return; } // // Define Temp Position for Selecting Max Position ... XPosition maxPos; maxPos.profit = INVALID_HANDLE; // // Define Temp Position for Selecting Min Position ... XPosition minPos; minPos.profit = INVALID_HANDLE; // // Loop through available Positions for Selecting Positions ... for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // // Check Profit State ... if (iPosition.profit >= 0) { continue; } // // Check Selection State ... if (isMinSelectable) { // if (minPos.profit == INVALID_HANDLE || minPos.profit < iPosition.profit) { minPos = iPosition; } // continue; } else if (isMaxSelectable) { // if (maxPos.profit == INVALID_HANDLE || maxPos.profit > iPosition.profit) { maxPos = iPosition; } // continue; } else { // Add( iPosition, result); } } // // Add Selected Position if Provided to Results ... if (isMinSelectable) { // Add( minPos, result); } else if (isMaxSelectable) { // Add( maxPos, result); } } // // Retrieve Orders ... void GetOrders( XOrder &result[], // Hold Result ... string symbol = NULL, // Trading Symbol ... ENUM_ORDER_TYPE type = NULL, // Trading Type ... ENUM_ORDER_STATE state = NULL, // Trading State ... ENUM_TIMEFRAMES period = NULL, // Trading Period ... string provider = NULL // Signal Provider ... ) { // Clean(result); // XOrder orders[]; mTrader.GetOrders( orders, symbol, period, state); int ordersCount = ArraySize(orders); if (ordersCount <= 0) { return; } // if (type == NULL && (provider == NULL || StringLen(provider) == 0)) { // Copy( orders, result); // return; } // for (int i = 0; i < ordersCount; i++) { // XOrder iOrder = orders[i]; // if (type != NULL && iOrder.type != type) { continue; } // if (provider != NULL && StringLen(provider) > 0) { // // Generate Order Provider ... string iProvider = ExtractProvider(iOrder.comment); if (iProvider != provider) { continue; } } // Add( iOrder, result); } } // // GUARD Handlers ... // // Parse Recievd Guards and Do them ... void DoGuards(XGuard &guards[]) { int guardsCount = ArraySize(guards); if (guardsCount <= 0) { return; } // for (int i = 0; i < guardsCount; i++) { // XGuard iGuard = guards[i]; // switch (iGuard.action) { // // Hedge In Profit Specified Positions ... case X_GUARD_ACTION_HEDGE: HandleGuardHedgeAction( iGuard.provider, iGuard.symbol, iGuard.type, iGuard.period); break; // // Trail Stop Loss in Specified Positions ... case X_GUARD_ACTION_TRAIL_STOP: HandleGuardTrailingStopAction( iGuard.provider, iGuard.symbol, iGuard.type, iGuard.period, iGuard.dblPayLoad); break; // // Force Close Specified Positions ... case X_GUARD_ACTION_FORCE_CLOSE: HandleGuardForceCloseAction( iGuard.provider, iGuard.symbol, iGuard.type, iGuard.period); break; // // Generate and Place Support Signals ... case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL: HandleGuardAddSupportPositionAction( iGuard.provider, iGuard.symbol, iGuard.type, iGuard.period); break; // // Delete All Placed Pending Orders ... case X_GUARD_ACTION_CANCEL_PENDING_ORDERS: HandleGuardCancelPendingOrdersAction( iGuard.provider, iGuard.symbol, iGuard.type, iGuard.period); break; } } } // // Close All Specified Provider's Positions in Profit Summary ... void HandleGuardHedgeAction( string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol ENUM_POSITION_TYPE type, // Trading Type ENUM_TIMEFRAMES period, // Specified Time Frame double minProfitForHedging = 1 // Specified Profit for Hedge ) { // } // // Close Max In Profit Trade Guard Action ... void HandleGuardCloseInProfitAction( string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol ENUM_POSITION_TYPE type, // Trading Type ENUM_TIMEFRAMES period, // Specified Time Frame ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method ) { // XPosition positions[]; GetInProfitPositions( positions, symbol, type, period, provider, method); int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return; } // string comment = "Close InProfit ..."; mTrader.ClosePositions( positions, comment); // string message = "Guard Close (" + ToString(positionsCount) + ") Postion(s) In Profit ..."; LogMessage(message); } // // Close Max In Drawdown Trade Guard Action ... void HandleGuardCloseInDrawdownAction( string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol ENUM_POSITION_TYPE type, // Trading Type ENUM_TIMEFRAMES period, // Specified Time Frame ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method ) { // XPosition positions[]; GetInDrawdownPositions( positions, symbol, type, period, provider, method); int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return; } // string comment = "Close InDrawdown ..."; mTrader.ClosePositions( positions, comment); // string message = "Guard Close (" + ToString(positionsCount) + ") Position(s) In Drawdown ..."; LogMessage(message); } // // Force Close Specified Set Of Position ... void HandleGuardForceCloseAction( string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol ENUM_POSITION_TYPE type, // Trading Type ENUM_TIMEFRAMES period, // Specified Time Frame ulong ticket = 0 // Specific Ticket ) { // string comment = ""; // // Close All Positions ... if (ticket == 0) { // XPosition positions[]; GetPositions( positions, symbol, type, period, provider); if (ArraySize(positions) <= 0) { return; } // comment = provider + " Force Close Guard ..."; // mTrader.ClosePositions( positions, comment); } // // Close Specific Position ... else { // XPosition position; bool hasPosition = mTrader.GetPosition( position, ticket); // if (hasPosition) { // comment = provider + "(" + ToString(ticket) + ")" + " Force Close Guard ..."; // mTrader.Close( ticket, comment); } } // if (StringLen(comment) > 0) { LogMessage(comment); } } // // Trailing Specified Set Of Positions Stop Losses ... void HandleGuardTrailingStopAction( string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol ENUM_POSITION_TYPE type, // Trading Type ENUM_TIMEFRAMES period, // Specified Time Frame double sl // Desired SL Value ... ) { // if (sl <= 0) { return; } // NormalizePrice( sl, symbol); // XPosition positions[]; GetPositions( positions, symbol, type, period, provider); int positionsCount = ArraySize(positions); if (positionsCount <= 0) { return; } // int modified = 0; for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // string comment = PrepareSLTrailComment(iPosition.comment); // bool isModified = mTrader.Modify( iPosition.ticket, sl, iPosition.tp, comment); if (isModified) { modified++; } } // if (modified > 0) { // string msg = "(" + ToString(modified) + ") Position's Stop Trailed Successfully ..."; // LogMessage(msg); } } // // Add Support Signal for Specified Positions ... void HandleGuardAddSupportPositionAction( string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol ENUM_POSITION_TYPE type, // Trading Type ENUM_TIMEFRAMES period // Specified Time Frame ) { // // TODO: Implement this ... } // // Cancel all Placed Orders ... void HandleGuardCancelPendingOrdersAction( string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol ENUM_POSITION_TYPE type, // Trading Type ENUM_TIMEFRAMES period // Specified Time Frame ) { // // TODO: Implement this ... } // // END Provided Functions ... // // // Protected ... protected: // string GetTagPrefix() { // string result = "(" + mSymbol + ")(" + ToString(mPeriod) + ")"; // return result; } // // Symbol ... string mSymbol; // // Period ... ENUM_TIMEFRAMES mPeriod; // // ExpertAdviser MAgic Number ... ulong mMagic; // // Slipppage ... int mSlippage; // // Tag Identifier ... string mTag; // bool mEnableLongs; bool mEnableShorts; // int mMaxAllowedPositions; double mMaxAllowedDrawDownFactor; // // Private ... private: // // Define Requirements ... // // XSCTrade Event Handlers ... TOnStopLoss mOnStopLossTriggered; TOnTakeProfit mOnTakeProfitTriggered; TOnDealsChanged mOnDealsChangedHandler; TOnOrdersChanged mOnOrdersChangedHandler; TOnPositionsChanged mOnPositionsChangedHandler; TOnTradeStateChanged mOnTradeStateChangedHandler; // // Initi Requirements ... void InitRequirements() { // // Account Manager ... mAccount = new XSCAccount(); // // Trader ... mTrader = new XSCTrade( mSlippage, mMagic); // // Attach Event Handlers ... // if (mOnStopLossTriggered != NULL) { mTrader.AddOnStopLossEventHandler(mOnStopLossTriggered); } // if (mOnTakeProfitTriggered != NULL) { mTrader.AddOnTakeProfitEventHandler(mOnTakeProfitTriggered); } // if (mOnDealsChangedHandler != NULL) { mTrader.AddOnDealsChangedEventHandler(mOnDealsChangedHandler); } // if (mOnOrdersChangedHandler != NULL) { mTrader.AddOnOrdersChangedEventHandler(mOnOrdersChangedHandler); } // if (mOnPositionsChangedHandler != NULL) { mTrader.AddOnPositionsChangedEventHandler(mOnPositionsChangedHandler); } // if (mOnTradeStateChangedHandler != NULL) { mTrader.AddOnTradeStateChangedEventHandler(mOnTradeStateChangedHandler); } } }; // // START Usefull Functions ... // // // END Usefull Functions ... //