/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XSCX121SMCBaseStrategy // Description: provides all based classes for use ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... // #include "../../Classes/x-saherelm.x-alert.class.mq5" #include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../../Classes/x-saherelm.x-poi.class.mq5" #include "../../Classes/x-saherelm.x-trade.class.mq5" #include "../Classes/x-121.smc.cobjects.class.mq5" #include "../Libraries/x-121.smc.lib.mq5" // // Helper(s) ... // // XStrategy Class Implementation(s) ... class XCX121SMCBaseStrategy : public XCBaseAlert { // // Public ... public: // // // Constructor(s) ... void XCX121SMCBaseStrategy( // // Base ... string _symbol, // Trading Symbol ENUM_TIMEFRAMES _period // Trading TimeFrame ) { // mSymbol = _symbol; mPeriod = _period; // Init(); } // // Deconstructor ... void ~XCX121SMCBaseStrategy() { DeInit(); } // // Getter / Setter (s) ... /** * Retrieve Symbol ... * * @return ( string ) */ string GetSymbol() { return mSymbol; } /** * Retrieve TimeFrame ... * * @return ( ENUM_TIMEFRAMES ) */ ENUM_TIMEFRAMES GetPeriod() { return mPeriod; } /** * Check Strategy is Disabled or not ... * * @return ( bool ) */ bool IsDisabled() { return mForceDisabled; } /** * Get Chart Id ... * * @return ( long ) */ long ChartIdentification() { return mChartID; } /** * Set Chart Id ... * * @param value: Long ... */ void ChartIdentification(long value) { // if (value < 0) { value = 0; } // mChartID = value; if (mPOIDrawer != NULL) { mPOIDrawer.ChartIdentification(value); } } /** * Get Sub Window Id ... * * @return ( int ) */ int SubWindowIdentification() { return mSubWindow; } /** * Set Sub Window Id ... * * @param value: Integer ... */ void SubWindowIdentification(int value) { // if (value < 0) { value = 0; } // mSubWindow = value; if (mPOIDrawer != NULL) { mPOIDrawer.SubWindowIdentification(value); } } /** * Get Signal Volume ... * * @return ( double ) */ double Volume() { return mVolume; } /** * Set Signal Volume ... * * @param value: Double ... */ void Volume(double value) { // if (value < 0.01) { value = 0.01; } // mVolume = value; } /** * Get Risk/Reward Ratio ... * * @return ( double ) */ double R2R() { return mR2R; } /** * Set Risk/Reward Ratio ... * * @param value: Double ... */ void R2R(double value) { // if (value < 0) { value = 1.5; } // mR2R = value; } /** * Get Max Allowed Spread ... * * @return ( double ) */ double MaxAllowedSpread() { return mMaxAllowedSpread; } /** * Set Max Allowed Spread ... * * @param value: Double ... */ void MaxAllowedSpread(double value) { mMaxAllowedSpread = value; } /** * Get Min Required Ticks Verification for Spread Pass ... * * @return ( int ) */ int MinRequiredTicksForSpreadPass() { return mMinRequiredTicksForSpreadPass; } /** * Set Min Required Ticks Verification for Spread Pass ... * * @param value: Integer ... */ void MinRequiredTicksForSpreadPass(int value) { // if (value < 100) { value = 100; } // mMinRequiredTicksForSpreadPass = value; } /** * Get Max Allowed Save Ticks ... * * @return ( int ) */ int MaxAllowedSaveTicks() { return mMaxAllowedSaveTicks; } /** * Set Max Allowed Save Ticks ... * * @param value: Integer ... */ void MaxAllowedSaveTicks(int value) { // if (value < 150) { value = 150; } // mMaxAllowedSaveTicks = value; } /** * Get Long Signalling State ... * * @return ( bool ) */ bool AllowLong() { return mAllowLong; } /** * Set Long Signalling State ... * * @param value: Boolean ... */ void AllowLong(bool value) { mAllowLong = value; } /** * Get Short Signalling State ... * * @return ( bool ) */ bool AllowShort() { return mAllowShort; } /** * Set Short Signalling State ... * * @param value: Argument 1 */ void AllowShort(bool value) { mAllowShort = value; } // // Actions ... /** * Disable Strategy ... */ void Disable() { mForceDisabled = true; } /** * Enable Strategy ... */ void Enable() { mForceDisabled = false; } /** * Register Signal Event Handler ... * * @param handler: an Instance of TOnXSignal ... */ void AddXSignalEventHandler(TOnX121SMCSignal handler) { // Add( handler, mSignalEventHandlers // ); } // // Virtual Actions ... /** * Destroy All Class Implementations ... */ virtual void Destroy() { } /** * Handle Tick Processing ... */ virtual void HandleTick() { // // Check State ... if (IsDisabled()) { return; } // // Check Signalling State ... if (!AllowLong() && !AllowShort()) { return; } // // Check Bar Tracker State ... if (!mBarTracker.CanProcessBar()) { return; } // // Retrieve Current Tick and Check it's Time // by Last Issued Tick ... MqlTick cTick; bool hasTick = GetTick( mSymbol, cTick // ); bool isSameAsLast = cTick.time == mLastTick.time; if (isSameAsLast) { return; } // // Update Last Issued Tick ... mLastTick = cTick; SaveTickData(); CleanupTicks(); // // Update POIs ... // // Trigger ... ENUM_XPOI_EVENTS mTriggerEvents[]; mTriggerDetector.Update(mTriggerEvents); mTriggerDetector.GetState(mTriggerState); // // Decision ... ENUM_XPOI_EVENTS mDecisionEvents[]; mDecisionDetector.Update(mDecisionEvents); mDecisionDetector.GetState(mDecisionState); // // Analyse ... ENUM_XPOI_EVENTS mAnalyseEvents[]; mAnalyseDetector.Update(mAnalyseEvents); mAnalyseDetector.GetState(mAnalyseState); // // Verification ... ENUM_XPOI_EVENTS mVerificationEvents[]; mVerificationDetector.Update(mVerificationEvents); mVerificationDetector.GetState(mVerificationState); // // Consolidation ... ENUM_XPOI_EVENTS mConsolidationEvents[]; mConsolidationDetector.Update(mConsolidationEvents); mConsolidationDetector.GetState(mConsolidationState); // // Vision ... ENUM_XPOI_EVENTS mVisionEvents[]; mVisionDetector.Update(mVisionEvents); mVisionDetector.GetState(mVisionState); // // Check Current Processing Tick has Signal or not ... XSignal signal; X121SMCStrategyConditions conditions; bool hasSignal = HasSignal( signal, conditions // ); if (!hasSignal) { return; } // // Waits Until Next Candle if Current Tick has Signal ... mBarTracker.Waits(); // // Notify Signal Event Handlers ... NotifyOnSignalEventHandlers( signal, conditions // ); } /** * Check For Signal ... * * @param signal: XSignal instance ... * @param conditions: X121SMCStrategyConditions instance ... * * @return ( virtual bool ) */ virtual bool HasSignal( XSignal &signal, X121SMCStrategyConditions &conditions // ) { // bool result = false; // signal.Clean(); conditions.Clean(); // return result; } /** * Detect SL Candidates based on Strategy and Conditions ... * * @param result: Double array reference ... * @param entry: Double, Position Entry Price ... * @param conditions: X121SMCStrategyConditions instance, Provides Configurations ... * @param type: ENUM_X_POSITION_TYPES member, Specified Position Type ... */ virtual void DetectSLCandidates( double &result[], double entry, X121SMCStrategyConditions &conditions, ENUM_X_POSITION_TYPES type // ) { } /** * Customize Strategy Identifier ... * * @return ( virtual string ) */ virtual string GetTag() { return X121SMCStrategyToken; } // // Protected ... protected: // // // Props ... // // Point Of Interests ... XCPOIDetector *mVisionDetector; XCPOIDetector *mConsolidationDetector; XCPOIDetector *mVerificationDetector; XCPOIDetector *mAnalyseDetector; XCPOIDetector *mDecisionDetector; XCPOIDetector *mTriggerDetector; // XPOIState mVisionState; XPOIState mConsolidationState; XPOIState mVerificationState; XPOIState mAnalyseState; XPOIState mDecisionState; XPOIState mTriggerState; // XCPOIDrawer *mPOIDrawer; // POI Drawer Class ... CArrayObj mDrawnObjects; // XTick mTicks[]; // Hold Ticks Data ... MqlTick mLastTick; // Last Issued Tick ... // XBarTracker mBarTracker; // Strategy Time Tracker ... XCBarAnalyser mBarAnalyser; // Bar Analyser Instance // X121SMCStrategyConditions mConditions; // Market Conditions ... // // Actions ... /** * Check Spread Passed for Positions... * * @return ( bool ) */ bool IsSpreadPass() { // bool result = false; // double pointValue = GetPoints(mSymbol); double maxAllowedSpread = MaxAllowedSpread(); int minRequiredTicksVerification = MinRequiredTicksForSpreadPass(); if (maxAllowedSpread > 0) { maxAllowedSpread *= pointValue; } else { maxAllowedSpread = 0; } // result = maxAllowedSpread <= 0 ? true : minRequiredTicksVerification > 0; if (!result) { return result; } // int ticksCount = ArraySize(mTicks); result = ticksCount >= minRequiredTicksVerification; if (!result) { return result; } // if (maxAllowedSpread > 0) { // int end = -1; int start = -1; result = CalculateTicksParams( start, end, minRequiredTicksVerification // ); if (!result) { return result; } // for (int i = start; i < end; i++) { // XTick iTick = mTicks[i]; // result = iTick.spread <= maxAllowedSpread; if (!result) { break; } } } // return result; } /** * Prepare and Normalize Signal for Execution in Strategy ... * * @param signal: XSignal instance ... * * @return ( bool ) */ bool PrepareSignal(XSignal &signal) { // bool result = false; // // Check Strategy Is Enables ... result = !IsDisabled(); if (!result) { return result; } // // Validate Signal ... result = signal.IsValid(); if (!result) { return result; } // bool isLong = IsLong(signal.type); // // TODO: Implement Signal Preparation Mechanism here ... // return result; } // /** * Notified Signal Event Handler(s) ... * * @param signal: XSignal instance ... * @param conditions: XStrategyConditions instance ... */ void NotifyOnSignalEventHandlers( XSignal &signal, X121SMCStrategyConditions &conditions // ) { // if (!signal.IsValid() || !conditions.IsValid()) { return; } // int count = ArraySize(mSignalEventHandlers); if (!IsValidSize(count)) { return; } // for (int i = 0; i < count; i++) { // mSignalEventHandlers[i]( signal, conditions // ); } } // // Draw Functions ... /** * Clear all Drawn Objects ... */ void ClearDraws() { mDrawnObjects.Clear(); } /** * Remove Specified Drawn Object ... * * @param name: Object name ... */ void RemoveObject(string name) { // if (!IsValid(name)) { return; } // int count = mDrawnObjects.Total(); if (!IsValidSize(count)) { return; } // int idx = -1; for (int i = 0; i < count; i++) { // string iName = ((CChartObject *)mDrawnObjects.At(i)).Name(); string iObjName = NULL; if (!IsValid(iName)) { iObjName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); } // if ((IsValid(iName) && iName == name) || (IsValid(iObjName) && iObjName == name)) { // idx = i; break; } } // if (IsValidIndex(idx)) { mDrawnObjects.Delete(idx); } } /** * Draw Specified Signal ... * * @param signal: XSignal instance ... */ void DrawSignal(XSignal &signal) { // if (!signal.IsValid()) { return; } // // DrawConditions(conditions); // string name = signal.GetTag(); RemoveObject(name); // XCSignalObject *iObj; iObj = new XCSignalObject(); // bool isCreated = iObj.Create( ChartIdentification(), name, SubWindowIdentification(), signal // ); if (!isCreated) { return; } // iObj.TPWidth(1); iObj.TPColor(clrGreen); iObj.TPWidth(STYLE_DOT); // iObj.SLWidth(1); iObj.SLColor(clrRed); iObj.SLWidth(STYLE_DOT); // iObj.EntryWidth(1); iObj.EntryColor(clrYellow); iObj.EntryWidth(STYLE_DOT); // mDrawnObjects.Add(iObj); } /** * Draw Specified State on Chart ... * * @param state: XPOIState instance ... */ void DrawState( XPOIState &state, bool forceUpdateTo = false, bool drawSwingHighs = true, bool drawSwingLows = true, bool drawSupportZones = true, bool drawResistanceZones = true, bool drawSupplyZones = true, bool drawDemandZones = true, bool drawBullishOrderBlocks = true, bool drawBearishOrderBlocks = true, bool drawBullishFairValueGaps = true, bool drawBearishFairValueGaps = true, bool drawBullishRejectionBars = true, bool drawBearishRejectionBars = true, bool drawBullishMomentumBars = true, bool drawBearishMomentumBars = true, bool drawTicksZone = true // ) { // int count = 0; datetime cTime = TimeCurrent(); // // Swings ... // // Swing Highs ... if (drawSwingHighs) { // count = ArraySize(state.swingHighs); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSwing item = state.swingHighs[i]; // XCSwingHighObject *iObj; bool isCreated = mPOIDrawer.CreateSwingHigh( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Swing Lows ... if (drawSwingLows) { // count = ArraySize(state.swingLows); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSwing item = state.swingLows[i]; // XCSwingLowObject *iObj; bool isCreated = mPOIDrawer.CreateSwingLow( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Support and Resistance Zones ... // // Support Zones ... if (drawSupportZones) { // count = ArraySize(state.supportZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSupportZone item = state.supportZones[i]; if (forceUpdateTo) { item.To(cTime); } // XCSupportZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupportZone( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Resistance Zones ... if (drawResistanceZones) { // count = ArraySize(state.resistanceZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCResistanceZone item = state.resistanceZones[i]; if (forceUpdateTo) { item.To(cTime); } // XCResistanceZoneObject *iObj; bool isCreated = mPOIDrawer.CreateResistanceZone( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Supply and Demand Zones ... // // Supply Zones ... if (drawSupplyZones) { // count = ArraySize(state.supplyZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSupplyZone item = state.supplyZones[i]; if (forceUpdateTo) { item.To(cTime); } // XCSupplyZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupplyZone( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Demand Zones ... if (drawDemandZones) { // count = ArraySize(state.demandZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCDemandZone item = state.demandZones[i]; if (forceUpdateTo) { item.To(cTime); } // XCDemandZoneObject *iObj; bool isCreated = mPOIDrawer.CreateDemandZone( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Order Blocks ... // // Bullish Order Blocks ... if (drawBullishOrderBlocks) { // count = ArraySize(state.bullishOrderBlocks); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCOrderBlock item = state.bullishOrderBlocks[i]; if (forceUpdateTo) { item.To(cTime); } // XCBullishOrderBlockObject *iObj; bool isCreated = mPOIDrawer.CreateBullishOrderBlock( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Bearish Order Blocks ... if (drawBearishOrderBlocks) { // count = ArraySize(state.bearishOrderBlocks); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCOrderBlock item = state.bearishOrderBlocks[i]; if (forceUpdateTo) { item.To(cTime); } // XCBearishOrderBlockObject *iObj; bool isCreated = mPOIDrawer.CreateBearishOrderBlock( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Fair Value Gaps ... // // Bullish Fair Value Gaps ... if (drawBullishFairValueGaps) { // count = ArraySize(state.bullishFairValueGaps); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCFVG item = state.bullishFairValueGaps[i]; if (forceUpdateTo) { item.To(cTime); } // XCBullishFairValueGapObject *iObj; bool isCreated = mPOIDrawer.CreateBullishFairValueGap( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Bearish Fair Value Gaps ... if (drawBearishFairValueGaps) { // count = ArraySize(state.bearishFairValueGaps); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCFVG item = state.bearishFairValueGaps[i]; if (forceUpdateTo) { item.To(cTime); } // XCBearishFairValueGapObject *iObj; bool isCreated = mPOIDrawer.CreateBearishFairValueGap( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Rejection Bars ... // // Bullish Rejection Bars ... if (drawBullishRejectionBars) { // count = ArraySize(state.bullishRejectionBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCRejectionBar item = state.bullishRejectionBars[i]; // XCBullishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBullishRejectionBar( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Bearish Rejection Bars ... if (drawBearishRejectionBars) { // count = ArraySize(state.bearishRejectionBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCRejectionBar item = state.bearishRejectionBars[i]; // XCBearishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBearishRejectionBar( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Momentum Bars ... // // Bullish Momentum Bars ... if (drawBullishMomentumBars) { // count = ArraySize(state.bullishMomentumBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCMomentumBar item = state.bullishMomentumBars[i]; // XCBullishMomentumBarObject *iObj; bool isCreated = mPOIDrawer.CreateBullishMomentumBar( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Bearish Momentum Bars ... if (drawBearishMomentumBars) { // count = ArraySize(state.bearishMomentumBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCMomentumBar item = state.bearishMomentumBars[i]; // XCBearishMomentumBarObject *iObj; bool isCreated = mPOIDrawer.CreateBearishMomentumBar( item, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } } // // Ticks Zone ... if (drawTicksZone && state.ticksZone != NULL) { // XCTicksZone *iZone = state.ticksZone; // if (forceUpdateTo) { iZone.To(cTime); } // XCTicksZoneObject *iObj; bool isCreated = mPOIDrawer.CreateTicksZone( iZone, iObj // ); if (isCreated) { AddObjectIfNotExists(iObj); } } } /** * Add Specified Object to Drawn Objects if not Exists ... */ void AddObjectIfNotExists(XCBaseObject *object) { // string name = object.ObjName(); // bool canAdd = true; int count = mDrawnObjects.Total(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); // if (name == iName) { // canAdd = false; break; } } } // if (canAdd) { mDrawnObjects.Add(object); } } // // Private ... private: // // Props ... // string mSymbol; // Trading Symbol ... ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame ... bool mForceDisabled; // Force Disabled ... bool mAllowLong; // Allow Long Signals bool mAllowShort; // Allow Short Signals double mR2R; // Risk/Rewar Ratio ... double mVolume; // Static Volume Per Trades ... // double mMaxAllowedSpread; // Max Allowed Spread ... int mMinRequiredTicksForSpreadPass; // Min Required Ticks Verification for Spread Pass ... int mMaxAllowedSaveTicks; // Max Allowed Save Ticks ... // long mChartID; // Chart ID ... int mSubWindow; // Sub Window ID ... // // On X121 Signal Recieved Event Handler(s) ... TOnX121SMCSignal mSignalEventHandlers[]; // // Actions ... /** * Install all Helpers and Prepare all Configurations for required Indicators ... */ void Init() { // mForceDisabled = false; // R2R(1); Volume(0.01); MaxAllowedSaveTicks(150); MinRequiredTicksForSpreadPass(100); // ChartIdentification(0); SubWindowIdentification(0); // // Configure POI Drawer if Required ... mPOIDrawer = new XCPOIDrawer(); mPOIDrawer.ChartIdentification(0); mPOIDrawer.SubWindowIdentification(0); // mPOIDrawer.DemandZoneFill(false); mPOIDrawer.SupplyZoneFill(false); mPOIDrawer.BullishFVGFill(false); mPOIDrawer.BearishFVGFill(false); mPOIDrawer.SupportZoneFill(false); mPOIDrawer.ResistanceZoneFill(false); mPOIDrawer.BullishOrderBlockFill(false); mPOIDrawer.BearishOrderBlockFill(false); // string symbol = Symbol(); ENUM_TIMEFRAMES period = Period(); // // Initialize Bar Tracker ... mBarTracker.Init( symbol, period // ); // // Initialize POIs ... // int poiRequired = 40; // // Trigger ... mTriggerDetector = new XCPOIDetector( symbol, PERIOD_M1 // ); mTriggerDetector.MaxNumberOfRequiredPOIs(poiRequired); mTriggerDetector.Init(); // // Decision ... mDecisionDetector = new XCPOIDetector( symbol, PERIOD_M5 // ); mDecisionDetector.MaxNumberOfRequiredPOIs(poiRequired); mDecisionDetector.Init(); // // Analyse ... mAnalyseDetector = new XCPOIDetector( symbol, PERIOD_M15 // ); mAnalyseDetector.MaxNumberOfRequiredPOIs(poiRequired); mAnalyseDetector.Init(); // // Verification ... mVerificationDetector = new XCPOIDetector( symbol, PERIOD_M30 // ); mVerificationDetector.MaxNumberOfRequiredPOIs(poiRequired); mVerificationDetector.Init(); // // Consolidation ... mConsolidationDetector = new XCPOIDetector( symbol, PERIOD_H1 // ); mConsolidationDetector.MaxNumberOfRequiredPOIs(poiRequired); mConsolidationDetector.Init(); // // Vision ... mVisionDetector = new XCPOIDetector( symbol, PERIOD_H4 // ); mVisionDetector.MaxNumberOfRequiredPOIs(poiRequired); mVisionDetector.Init(); // } /** * De Initialize all Tools ... */ void DeInit() { // delete mVisionDetector; delete mConsolidationDetector; delete mVerificationDetector; delete mAnalyseDetector; delete mDecisionDetector; delete mTriggerDetector; // delete mPOIDrawer; // Destroy(); } /** * Reste Bar Tracker ... */ void ResetBarTracker() { mBarTracker.Clean(); } /** * Cleanup Ticks Size ... */ void CleanupTicks() { // int maxRequiredTicks = MaxAllowedSaveTicks(); int ticksCount = ArraySize(mTicks); if (!IsValidSize(ticksCount) || ticksCount <= maxRequiredTicks) { return; } // int removeCount = ticksCount - maxRequiredTicks; if (!IsValidSize(removeCount)) { return; } // ArrayRemove( mTicks, 0, removeCount // ); } /** * Add new Tick Data to Collection ... */ void SaveTickData() { // XTick tick; bool isInited = tick.Init(mSymbol); if (!isInited) { return; } // AddRef( tick, mTicks // ); } /** * Calculate Ticks Param for Looping through Last n items ... * * @param start: Integer Reference to Start ... * @param end: Integer Reference to End ... * @param numOfLastTicks: Integer Max Number of Required N Last Ticks ... */ bool CalculateTicksParams( int &start, int &end, int numOfLastTicks = 5 // ) { // bool result = 0; // start = -1; end = -1; // int count = ArraySize(mTicks); // start = count - numOfLastTicks; if (start < 0) { start = 0; } // end = start + numOfLastTicks; if (end > count) { end = count; } // result = IsValidIndex(start) && IsValidIndex(end); // return result; } // }; //