//+--------------------------------------------------------------------+ //| Copyright: (C) 2016 Forex Software Ltd. | //| Website: http://forexsb.com/ | //| Support: http://forexsb.com/forum/ | //| License: Proprietary under the following circumstances: | //+--------------------------------------------------------------------+ #property copyright "Copyright (C) 2016 Forex Software Ltd." #property link "http://forexsb.com" #property version "49.0" #property strict // ----------------------- External variables ----------------------- // static input string StrategyProperties__="------------"; // ------ Strategy Properties ------ static input double Entry_Amount = 0.1; // Amount for a new position [lot] static input double Maximum_Amount = 1; // Maximum position amount [lot] static input double Adding_Amount = 0.1; // Amount to add on addition [lot] static input double Reducing_Amount = 0.1; // Amount to close on reduction [lot] input int Stop_Loss = 1645; // Stop Loss [point] input int Take_Profit = 0; // Take Profit [point] input int Break_Even = 0; // Break Even [point] static input double Martingale_Multiplier=0; // Martingale Multiplier static input string IndicatorName0 = "Vidya Moving Average"; // ------ Indicator parameters ------ input int Slot0IndParam0 = 21; // Period input int Slot0IndParam1 = 5; // Smooth static input string IndicatorName1 = "Top Bottom Price"; // ------ Indicator parameters ------ input int Slot1IndParam0 = 0; // Vertical shift static input string IndicatorName2 = "MA Oscillator"; // ------ Indicator parameters ------ input int Slot2IndParam0 = 13; // Fast MA period input int Slot2IndParam1 = 21; // Slow MA period input double Slot2IndParam2 = 0; // Level static input string IndicatorName3 = "Parabolic SAR"; // ------ Indicator parameters ------ input double Slot3IndParam0 = 0.02; // Starting AF input double Slot3IndParam1 = 0.02; // Increment input double Slot3IndParam2 = 2; // Maximum AF static input string IndicatorName4 = "ROC MA Oscillator"; // ------ Indicator parameters ------ input int Slot4IndParam0 = 10; // ROC period input int Slot4IndParam1 = 14; // Signal line period static input string IndicatorName5 = "Hourly High Low"; // ------ Indicator parameters ------ input int Slot5IndParam0 = 0; // Start hour (incl.) input int Slot5IndParam1 = 0; // Start minutes (incl.) input int Slot5IndParam2 = 24; // End hour (excl.) input int Slot5IndParam3 = 0; // End minutes (excl.) input int Slot5IndParam4 = 0; // Vertical shift static input string ExpertSettings__="------------"; // ------ Expert Settings ------ // If account equity drops below this value, the expert will close out all positions and stop automatic trade. // The value must be set in account currency. Example: // Protection_Min_Account = 700 will close positions if the equity drops below 700 USD (EUR if you account is in EUR). static input int Protection_Min_Account=0; // Stop trading at min account // The expert checks the open positions at every tick and if found no SL or SL lower (higher for short) than selected, // It sets SL to the defined value. The value is in points. Example: // Protection_Max_StopLoss = 200 means 200 pips for 4 digit broker and 20 pips for 5 digit broker. static input int Protection_Max_StopLoss=0; // Ensure maximum Stop Loss [point] // How many seconds before the expected bar closing to rise a Bar Closing event. static input int Bar_Close_Advance=15; // Bar closing advance [sec] // Expert writes a log file when Write_Log_File = true. static input bool Write_Log_File=false; // Write a log file // Custom comment. It can be used for setting a binnary option epxiration perod static input string Order_Comment=""; // Custom order comment // ---------------------------- Options ---------------------------- // // Data bars for calculating the indicator values with the necessary precission. // If set to 0, the expert calculates them automatically. int Min_Data_Bars=0; // It hase to be set to true for STP brokers that cannot set SL and TP together with the position (with OrderSend()). // When Separate_SL_TP = true, the expert first opens the position and after that sets StopLoss and TakeProfit. bool Separate_SL_TP=false; // Separate SL and TP orders // TrailingStop_Moving_Step determines the step of changing the Trailing Stop. // 0 <= TrailingStop_Moving_Step <= 2000 // If TrailingStop_Moving_Step = 0, the Trailing Stop trails at every new extreme price in the position's direction. // If TrailingStop_Moving_Step > 0, the Trailing Stop moves at steps equal to the number of pips chosen. // This prevents sending multiple order modifications. int TrailingStop_Moving_Step=10; // When the log file reaches the preset number of lines, // the expert starts a new log file. int Max_Log_Lines_in_File=2000; // Used to detect a chart change string __symbol = ""; int __period = -1; enum DataPeriod { DataPeriod_M1 = 1, DataPeriod_M5 = 5, DataPeriod_M15 = 15, DataPeriod_M30 = 30, DataPeriod_H1 = 60, DataPeriod_H4 = 240, DataPeriod_D1 = 1440, DataPeriod_W1 = 10080, DataPeriod_MN1 = 43200 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum PosDirection { PosDirection_None, PosDirection_Long, PosDirection_Short, PosDirection_Closed }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OrderDirection { OrderDirection_None, OrderDirection_Buy, OrderDirection_Sell }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum StrategyPriceType { StrategyPriceType_Open, StrategyPriceType_Close, StrategyPriceType_Indicator, StrategyPriceType_CloseAndReverse, StrategyPriceType_Unknown }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum ExecutionTime { ExecutionTime_DuringTheBar, ExecutionTime_AtBarOpening, ExecutionTime_AtBarClosing, ExecutionTime_CloseAndReverse }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TraderOrderType { TraderOrderType_Buy = 0, TraderOrderType_Sell = 1, TraderOrderType_BuyLimit = 2, TraderOrderType_SellLimit = 3, TraderOrderType_BuyStop = 4, TraderOrderType_SellStop = 5 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TradeDirection { TradeDirection_None, TradeDirection_Long, TradeDirection_Short, TradeDirection_Both }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum LongTradeEntryPrice { LongTradeEntryPrice_Bid, LongTradeEntryPrice_Ask, LongTradeEntryPrice_Chart }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OperationType { OperationType_Buy, OperationType_Sell, OperationType_Close, OperationType_Modify }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TickType { TickType_Open = 0, TickType_OpenClose = 1, TickType_Regular = 2, TickType_Close = 3, TickType_AfterClose = 4 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum InstrumentType { InstrumentType_Forex, InstrumentType_CFD, InstrumentType_Index }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum SlotTypes { SlotTypes_NotDefined = 0, SlotTypes_Open = 1, SlotTypes_OpenFilter = 2, SlotTypes_Close = 4, SlotTypes_CloseFilter = 8 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum IndComponentType { IndComponentType_NotDefined, IndComponentType_OpenLongPrice, IndComponentType_OpenShortPrice, IndComponentType_OpenPrice, IndComponentType_CloseLongPrice, IndComponentType_CloseShortPrice, IndComponentType_ClosePrice, IndComponentType_OpenClosePrice, IndComponentType_IndicatorValue, IndComponentType_AllowOpenLong, IndComponentType_AllowOpenShort, IndComponentType_ForceCloseLong, IndComponentType_ForceCloseShort, IndComponentType_ForceClose, IndComponentType_Other }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum PositionPriceDependence { PositionPriceDependence_None, PositionPriceDependence_PriceBuyHigher, PositionPriceDependence_PriceBuyLower, PositionPriceDependence_PriceSellHigher, PositionPriceDependence_PriceSellLower, PositionPriceDependence_BuyHigherSellLower, PositionPriceDependence_BuyLowerSelHigher,// Deprecated PositionPriceDependence_BuyLowerSellHigher }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum BasePrice { BasePrice_Open = 0, BasePrice_High = 1, BasePrice_Low = 2, BasePrice_Close = 3, BasePrice_Median = 4, // Price[bar] = (Low[bar] + High[bar]) / 2; BasePrice_Typical = 5, // Price[bar] = (Low[bar] + High[bar] + Close[bar]) / 3; BasePrice_Weighted = 6 // Price[bar] = (Low[bar] + High[bar] + 2 * Close[bar]) / 4; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum MAMethod { MAMethod_Simple = 0, MAMethod_Weighted = 1, MAMethod_Exponential = 2, MAMethod_Smoothed = 3 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum SameDirSignalAction { SameDirSignalAction_Nothing, SameDirSignalAction_Add, SameDirSignalAction_Winner, SameDirSignalAction_Loser, }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OppositeDirSignalAction { OppositeDirSignalAction_Nothing, OppositeDirSignalAction_Reduce, OppositeDirSignalAction_Close, OppositeDirSignalAction_Reverse }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum PermanentProtectionType { PermanentProtectionType_Relative, PermanentProtectionType_Absolute }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TrailingStopMode { TrailingStopMode_Bar, TrailingStopMode_Tick }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum IndicatorLogic { IndicatorLogic_The_indicator_rises, IndicatorLogic_The_indicator_falls, IndicatorLogic_The_indicator_is_higher_than_the_level_line, IndicatorLogic_The_indicator_is_lower_than_the_level_line, IndicatorLogic_The_indicator_crosses_the_level_line_upward, IndicatorLogic_The_indicator_crosses_the_level_line_downward, IndicatorLogic_The_indicator_changes_its_direction_upward, IndicatorLogic_The_indicator_changes_its_direction_downward, IndicatorLogic_The_price_buy_is_higher_than_the_ind_value, IndicatorLogic_The_price_buy_is_lower_than_the_ind_value, IndicatorLogic_The_price_open_is_higher_than_the_ind_value, IndicatorLogic_The_price_open_is_lower_than_the_ind_value, IndicatorLogic_It_does_not_act_as_a_filter, }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum BandIndLogic { BandIndLogic_The_bar_opens_below_the_Upper_Band, BandIndLogic_The_bar_opens_above_the_Upper_Band, BandIndLogic_The_bar_opens_below_the_Lower_Band, BandIndLogic_The_bar_opens_above_the_Lower_Band, BandIndLogic_The_position_opens_below_the_Upper_Band, BandIndLogic_The_position_opens_above_the_Upper_Band, BandIndLogic_The_position_opens_below_the_Lower_Band, BandIndLogic_The_position_opens_above_the_Lower_Band, BandIndLogic_The_bar_opens_below_Upper_Band_after_above, BandIndLogic_The_bar_opens_above_Upper_Band_after_below, BandIndLogic_The_bar_opens_below_Lower_Band_after_above, BandIndLogic_The_bar_opens_above_Lower_Band_after_below, BandIndLogic_The_bar_closes_below_the_Upper_Band, BandIndLogic_The_bar_closes_above_the_Upper_Band, BandIndLogic_The_bar_closes_below_the_Lower_Band, BandIndLogic_The_bar_closes_above_the_Lower_Band, BandIndLogic_It_does_not_act_as_a_filter }; //+------------------------------------------------------------------+ bool LabelCreate(const long chart_ID = 0, // chart's ID const string name = "Label", // label name const int sub_window = 0, // subwindow index const int x = 0, // X coordinate const int y = 0, // Y coordinate const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER,// chart corner for anchoring const string text = "Label", // text const string font = "Arial", // font const int font_size = 8, // font size const color clr = clrWhite, // color const double angle = 0.0, // text slope const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER,// anchor type const bool back = false, // in the background const bool selection = false, // highlight to move const bool hidden = true, // hidden in the object list const string tooltip = "\n", // sets the tooltip const long z_order = 0) // priority for mouse click { ResetLastError(); if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)) { Print(__FUNCTION__,": failed to create text label! Error code = ",GetLastError()); return (false); } ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); ObjectSetString(chart_ID,name,OBJPROP_FONT,font); ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size); ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle); ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor); ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); ObjectSetString(chart_ID,name,OBJPROP_TOOLTIP,tooltip); ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool LabelTextChange(const long chart_ID,const string name,const string text) { ResetLastError(); if(!ObjectSetString(chart_ID,name,OBJPROP_TEXT,text)) { Print(__FUNCTION__,": failed to change the text! Error code = ",GetLastError()); return (false); } return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool LabelDelete(const long chart_ID=0,const string name="Label") { if(!ObjectDelete(chart_ID,name)) { Print(__FUNCTION__,": failed to delete a text label! Error code = ",GetLastError()); return (false); } return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ color GetChartForeColor(const long chartId=0) { long foreColor=clrWhite; ChartGetInteger(chartId,CHART_COLOR_FOREGROUND,0,foreColor); return ((color) foreColor); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ color GetChartBackColor(const long chartId=0) { long backColor=clrBlack; ChartGetInteger(chartId,CHART_COLOR_BACKGROUND,0,backColor); return ((color) backColor); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string LoadStringFromFile(string filename) { string text; int intSize; int handle= FileOpen(filename,FILE_TXT|FILE_READ|FILE_ANSI); if(handle == INVALID_HANDLE) return ""; while(!FileIsEnding(handle)) { intSize=FileReadInteger(handle,INT_VALUE); text+=FileReadString(handle,intSize); } FileClose(handle); return text; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void SaveStringToFile(string filename,string text) { int handle= FileOpen(filename,FILE_TXT|FILE_WRITE|FILE_ANSI); if(handle == INVALID_HANDLE) return; FileWriteString(handle,text); FileClose(handle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ArrayContainsString(const string &array[],string text) { for(int i=0; iindexFromEnd) ? Value[bars-indexFromEnd-1]: 0; return (lastValue); } //+------------------------------------------------------------------+ class ListParameter { public: // Constructors ListParameter() { Caption = ""; Text = ""; Index = -1; Enabled = false; } // Properties string Caption; string Text; int Index; bool Enabled; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class NumericParameter { public: // Constructor NumericParameter() { Caption = ""; Value = 0; Enabled = false; } // Properties string Caption; double Value; bool Enabled; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CheckParameter { public: // Constructor CheckParameter() { Caption = ""; Checked = false; Enabled = false; } // Properties string Caption; bool Checked; bool Enabled; }; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Indicator { protected: double Sigma(void); double Epsilon(void); void NormalizeComponentValue(const double &componentValue[],const datetime &strategyTime[], int ltfShift,bool isCloseFilterShift,double &output[]); int NormalizeComponentFirstBar(int componentFirstBar,datetime &strategyTime[]); bool IsSignalComponent(IndComponentType componentType); void Price(BasePrice priceType,double &price[]); void MovingAverage(int period,int shift,MAMethod maMethod,const double &source[],double &movingAverage[]); void OscillatorLogic(int firstBar,int previous,const double &adIndValue[],double levelLong,double levelShort, IndicatorComp &indCompLong,IndicatorComp &indCompShort,IndicatorLogic indLogic); void NoDirectionOscillatorLogic(int firstBar,int previous,const double &adIndValue[],double dLevel, IndicatorComp &indComp,IndicatorLogic indLogic); void BandIndicatorLogic(int firstBar,int previous,const double &adUpperBand[],const double &adLowerBand[], IndicatorComp &indCompLong,IndicatorComp &indCompShort,BandIndLogic indLogic); void IndicatorRisesLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorFallsLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorChangesItsDirectionUpward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void IndicatorChangesItsDirectionDownward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void IndicatorIsHigherThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorIsLowerThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorCrossesAnotherIndicatorUpwardLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorCrossesAnotherIndicatorDownwardLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void BarOpensAboveIndicatorLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void BarOpensBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void BarOpensAboveIndicatorAfterOpeningBelowLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void BarOpensBelowIndicatorAfterOpeningAboveLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void BarClosesAboveIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void BarClosesBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); public: // Constructors Indicator(void); ~Indicator(void); // Properties string IndicatorName; string WarningMessage; bool IsDiscreteValues; bool UsePreviousBarValue; // Important! Otdated Do not use. bool IsSeparateChart; bool IsBacktester; bool IsDeafultGroupAll; // Important! Outdated. Do not use. bool IsDefaultGroupAll; bool IsAllowLTF; SlotTypes SlotType; ExecutionTime ExecTime; ListParameter *ListParam[5]; NumericParameter *NumParam[6]; CheckParameter *CheckParam[2]; IndicatorComp *Component[10]; DataSet *Data; // Methods virtual void Calculate(DataSet &dataSet); void NormalizeComponents(DataSet &strategyDataSet,int ltfShift,bool isCloseFilterShift); void ShiftSignal(int shift); void RepeatSignal(int repeat); int Components(void); string IndicatorParamToString(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Indicator::Indicator(void) { IndicatorName=""; IsBacktester = false; IsDiscreteValues = false; IsSeparateChart = false; IsDeafultGroupAll = false; IsDefaultGroupAll = false; IsAllowLTF = true; SlotType = SlotTypes_NotDefined; ExecTime = ExecutionTime_DuringTheBar; for(int i=0; i<5; i++) ListParam[i]=new ListParameter(); for(int i=0; i<6; i++) NumParam[i]=new NumericParameter(); for(int i=0; i<2; i++) CheckParam[i]=new CheckParameter(); for(int i=0; i<10; i++) Component[i]=new IndicatorComp(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Indicator::~Indicator(void) { for(int i=0; i<5; i++) delete ListParam[i]; for(int i=0; i<6; i++) delete NumParam[i]; for(int i=0; i<2; i++) delete CheckParam[i]; for(int i=0; i<10; i++) delete Component[i]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::Calculate(DataSet &dataSet) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::NormalizeComponents(DataSet &strategyDataSet,int ltfShift,bool isCloseFilterShift) { for(int i=0; i=ltfOpenTime && time=ltfCloseTime) break; } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int Indicator::NormalizeComponentFirstBar(int componentFirstBar,datetime &strategyTime[]) { datetime firstBarTime=Data.Time[componentFirstBar]; for(int bar=0; bar=firstBarTime) return bar; return componentFirstBar; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Indicator::IsSignalComponent(IndComponentType componentType) { return componentType == IndComponentType_AllowOpenLong || componentType == IndComponentType_AllowOpenShort || componentType == IndComponentType_CloseLongPrice || componentType == IndComponentType_ClosePrice || componentType == IndComponentType_CloseShortPrice || componentType == IndComponentType_ForceClose || componentType == IndComponentType_ForceCloseLong || componentType == IndComponentType_ForceCloseShort || componentType == IndComponentType_OpenClosePrice || componentType == IndComponentType_OpenLongPrice || componentType == IndComponentType_OpenPrice || componentType == IndComponentType_OpenShortPrice; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int Indicator::Components(void) { for(int i=0; i<10; i++) if(Component[i].DataType==IndComponentType_NotDefined) return (i); return (10); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Indicator::IndicatorParamToString(void) { string text; for(int i=0; i<5; i++) if(ListParam[i].Enabled) text+=StringFormat("%s: %s\n",ListParam[i].Caption,ListParam[i].Text); for(int i=0; i<6; i++) if(NumParam[i].Enabled) text+=StringFormat("%s: %g\n",NumParam[i].Caption,NumParam[i].Value); for(int i=0; i<2; i++) if(CheckParam[i].Enabled) text+=StringFormat("%s: %s\n",CheckParam[i].Caption,(CheckParam[i].Checked ? "Yes" : "No")); return (text); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::Price(BasePrice priceType,double &price[]) { ArrayResize(price,Data.Bars); ArrayInitialize(price,0); switch(priceType) { case BasePrice_Open: ArrayCopy(price,Data.Open); break; case BasePrice_High: ArrayCopy(price,Data.High); break; case BasePrice_Low: ArrayCopy(price,Data.Low); break; case BasePrice_Close: ArrayCopy(price,Data.Close); break; case BasePrice_Median: for(int bar=0; barbars || period+shift<=0 || period+shift>bars) { // Error in the parameters string message=IndicatorName+" "+Data.Symbol+" "+DataPeriodToString(Data.Period)+ "Wrong MovingAverage parameters(Period: "+IntegerToString(period)+ ", Shift: "+IntegerToString(shift)+ ", Source bars: "+IntegerToString(bars)+")"; Print(message); ArrayCopy(movingAverage,source); return; } for(int bar=0; baradIndValue[baseBar]; if(!IsDiscreteValues) // Aroon oscillator uses IsDiscreteValues = true { bool isNoChange=true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } } indCompLong.Value[bar] = adIndValue[baseBar] < adIndValue[currentBar] - sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[baseBar] > adIndValue[currentBar] + sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_falls: for(int bar=firstBar; bar adIndValue[baseBar]; if(!IsDiscreteValues) // Aroon oscillator uses IsDiscreteValues = true { bool isNoChange=true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } } indCompLong.Value[bar] = adIndValue[baseBar] > adIndValue[currentBar] + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[baseBar] < adIndValue[currentBar] - sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_is_higher_than_the_level_line: for(int bar=firstBar; bar levelLong + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[bar - previous] < levelShort - sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_is_lower_than_the_level_line: for(int bar=firstBar; bar levelShort + sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_crosses_the_level_line_upward: for(int bar=firstBar; barfirstBar) baseBar--; indCompLong.Value[bar]=(adIndValue[baseBar]levelLong+sigma) ? 1 : 0; indCompShort.Value[bar]=(adIndValue[baseBar]>levelShort+sigma && adIndValue[bar-previous]firstBar) baseBar--; indCompLong.Value[bar]=(adIndValue[baseBar]>levelLong+sigma && adIndValue[bar-previous]levelShort+sigma) ? 1 : 0; } break; case IndicatorLogic_The_indicator_changes_its_direction_upward: for(int bar=firstBar; barfirstBar) bar1--; int iBar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[iBar2])firstBar) iBar2--; indCompLong.Value[bar]=(adIndValue[iBar2]>adIndValue[bar1] && adIndValue[bar1]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; } break; case IndicatorLogic_The_indicator_changes_its_direction_downward: for(int bar=firstBar; barfirstBar) bar1--; int iBar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[iBar2])firstBar) iBar2--; indCompLong.Value[bar]=(adIndValue[iBar2]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; indCompShort.Value[bar]=(adIndValue[iBar2]>adIndValue[bar1] && adIndValue[bar1] adIndValue[baseBar]; bool isNoChange = true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } indComp.Value[bar]=adIndValue[baseBar] adIndValue[baseBar]; bool isNoChange = true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } indComp.Value[bar]=adIndValue[baseBar]>adIndValue[currentBar]+sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_is_higher_than_the_level_line: for(int bar=firstBar; bardLevel+sigma ? 1 : 0; break; case IndicatorLogic_The_indicator_is_lower_than_the_level_line: for(int bar=firstBar; barfirstBar) baseBar--; indComp.Value[bar]=(adIndValue[baseBar]dLevel+sigma) ? 1 : 0; } break; case IndicatorLogic_The_indicator_crosses_the_level_line_downward: for(int bar=firstBar; barfirstBar) baseBar--; indComp.Value[bar]=(adIndValue[baseBar]>dLevel+sigma && adIndValue[bar-previous]firstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indComp.Value[bar]=(adIndValue[bar2]>adIndValue[bar1] && adIndValue[bar1]firstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indComp.Value[bar]=(adIndValue[bar2]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; } break; default: return; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BandIndicatorLogic(int firstBar,int previous,const double &adUpperBand[],const double &adLowerBand[], IndicatorComp &indCompLong,IndicatorComp &indCompShort,BandIndLogic indLogic) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adLowerBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_above_the_Upper_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Open[bar] < adLowerBand[bar - previous] - sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_below_the_Lower_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_above_the_Lower_Band: for(int bar=firstBar; bar adLowerBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Open[bar] < adUpperBand[bar - previous] - sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_below_Upper_Band_after_above: for(int bar=firstBar; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]adUpperBand[baseBar-previous]+sigma ? 1 : 0; baseBar=bar-1; while(MathAbs(Data.Open[baseBar]-adLowerBand[baseBar-previous])firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]>adLowerBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]>adUpperBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]adLowerBand[baseBar-previous]+sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_below_Lower_Band_after_above: for(int bar=firstBar; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]adLowerBand[baseBar-previous]+sigma ? 1 : 0; baseBar=bar-1; while(MathAbs(Data.Open[baseBar]-adUpperBand[baseBar-previous])firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]>adUpperBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]>adLowerBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]adUpperBand[baseBar-previous]+sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_below_the_Upper_Band: for(int bar=firstBar; bar adLowerBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_above_the_Upper_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Close[bar] < adLowerBand[bar - previous] - sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_below_the_Lower_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_above_the_Lower_Band: for(int bar=firstBar; bar adLowerBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Close[bar] < adUpperBand[bar - previous] - sigma ? 1 : 0; } break; default: return; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorRisesLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adIndValue[baseBar]; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } indCompLong.Value[bar] = adIndValue[currentBar] > adIndValue[baseBar] + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[currentBar] < adIndValue[baseBar] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorFallsLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) { isNoChange=(isLower==(adIndValue[baseBar+1] adIndValue[baseBar] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorIsHigherThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adAnotherIndValue[currentBar] + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[currentBar] < adAnotherIndValue[currentBar] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorIsLowerThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adAnotherIndValue[currentBar] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorChangesItsDirectionUpward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma= Sigma(); for(int bar = firstBar; barfirstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indCompLong.Value[bar]=(adIndValue[bar2]>adIndValue[bar1] && adIndValue[bar1]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorChangesItsDirectionDownward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma= Sigma(); for(int bar = firstBar; barfirstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indCompLong.Value[bar]=(adIndValue[bar2]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; indCompShort.Value[bar]=(adIndValue[bar2]>adIndValue[bar1] && adIndValue[bar1]firstBar) baseBar--; indCompLong.Value[bar]=adIndValue[currentBar]>adAnotherIndValue[currentBar]+sigma && adIndValue[baseBar]adAnotherIndValue[baseBar]+sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorCrossesAnotherIndicatorDownwardLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) { baseBar--; } indCompLong.Value[bar]=adIndValue[currentBar]adAnotherIndValue[baseBar]+sigma ? 1 : 0; indCompShort.Value[bar]=adIndValue[currentBar]>adAnotherIndValue[currentBar]+sigma && adIndValue[baseBar] adIndValue[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Open[bar] < adIndValue[bar - previous] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarOpensBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adIndValue[bar - previous] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarOpensAboveIndicatorAfterOpeningBelowLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]>adIndValue[bar-previous]+sigma && Data.Open[baseBar]adIndValue[baseBar-previous]+sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarOpensBelowIndicatorAfterOpeningAboveLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]adIndValue[baseBar-previous]+sigma ? 1 : 0; indCompShort.Value[bar]=Data.Open[bar]>adIndValue[bar-previous]+sigma && Data.Open[baseBar] adIndValue[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Close[bar] < adIndValue[bar - previous] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarClosesBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adIndValue[bar - previous] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ class RateofChange : public Indicator { public: RateofChange(SlotTypes slotType) { SlotType=slotType; IndicatorName="Rate of Change"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = true; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void RateofChange::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); // Reading the parameters MAMethod method=(MAMethod) ListParam[1].Index; BasePrice basePrice=(BasePrice) ListParam[2].Index; int period = (int) NumParam[0].Value; int smooth = (int) NumParam[1].Value; double level=NumParam[2].Value; int previous=CheckParam[0].Checked ? 1 : 0; int firstBar=previous+period+smooth+2; double price[]; Price(basePrice,price); double roc[]; ArrayResize(roc,Data.Bars); ArrayInitialize(roc,0); for(int bar=period; bar=fromTime && barTimetoTime) isOnTime=barTime>=fromTime || barTime Data.Low[bar]) dMinPrice = Data.Low[bar]; } if(!isOnTime && isOnTimePrev) { adHighPrice[bar]= dMaxPrice; adLowPrice[bar] = dMinPrice; dMaxPrice = DBL_MIN; dMinPrice = DBL_MAX; } else { adHighPrice[bar] = adHighPrice[bar - 1]; adLowPrice[bar] = adLowPrice[bar - 1]; } isOnTimePrev=isOnTime; } double adUpperBand[]; ArrayResize(adUpperBand,Data.Bars); ArrayInitialize(adUpperBand,0); double adLowerBand[]; ArrayResize(adLowerBand,Data.Bars); ArrayInitialize(adLowerBand,0); for(int bar=firstBar; barData.Open[0]) { aiDir[0] = 1; aiDir[1] = 1; dPExtr=MathMax(Data.High[0],Data.High[1]); adPsar[1]=MathMin(Data.Low[0],Data.Low[1]); } else { aiDir[0] = -1; aiDir[1] = -1; dPExtr=MathMin(Data.Low[0],Data.Low[1]); adPsar[1]=MathMax(Data.High[0],Data.High[1]); } for(int bar=2; bar0 && adPsar[bar]>MathMin(Data.Low[bar-1],Data.Low[bar-2])) adPsar[bar]=MathMin(Data.Low[bar-1],Data.Low[bar-2]); else if(aiDir[bar]<0 && adPsar[bar]0 && Data.High[bar]>dPExtr) { dPExtr=Data.High[bar]; dAf=MathMin(dAf+dAfInc,dAfMax); } if(aiDir[bar]<0 && Data.Low[bar]0 ? Data.High[bar]: Data.Low[bar]; } } const int firstBar=8; // Saving the components ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "PSAR value"; Component[0].DataType = SlotType == SlotTypes_Close ? IndComponentType_ClosePrice : IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; Component[0].PosPriceDependence=PositionPriceDependence_BuyHigherSellLower; ArrayCopy(Component[0].Value,adPsar); } //+------------------------------------------------------------------+ class ROCMAOscillator : public Indicator { public: ROCMAOscillator(SlotTypes slotType) { SlotType=slotType; IndicatorName="ROC MA Oscillator"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = true; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ROCMAOscillator::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); // Reading the parameters MAMethod maMethod=(MAMethod) ListParam[2].Index; int period1 = (int) NumParam[0].Value; int period2 = (int) NumParam[1].Value; int previous=CheckParam[0].Checked ? 1 : 0; // Calculation int firstBar=MathMax(period1, period2) + previous + 2; double oscillator[]; ArrayResize(oscillator,Data.Bars); ArrayInitialize(oscillator,0); // ---------------------------------------------------- RateofChange *roc1=new RateofChange(SlotType); roc1.ListParam[1].Index = ListParam[1].Index; roc1.ListParam[2].Index = ListParam[3].Index; roc1.NumParam[0].Value=NumParam[0].Value; roc1.CheckParam[0].Checked=CheckParam[0].Checked; roc1.Calculate(dataSet); double indicator1[]; ArrayResize(indicator1,Data.Bars); ArrayCopy(indicator1,roc1.Component[0].Value); delete roc1; double indicator2[]; MovingAverage(period2,0,maMethod,indicator1,indicator2); // ----------------------------------------------------- for(int bar=firstBar; bar3); break; case 3: // Previous month isPeriodChanged=(time0.mon!=time1.mon); break; } return isPeriodChanged; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void TopBottomPrice::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); // Reading the parameters double shift=NumParam[0].Value*Data.Point; const int firstBar=2; // Calculation double topPrice[]; ArrayResize(topPrice,Data.Bars); ArrayInitialize(topPrice,0); double bottomPrice[]; ArrayResize(bottomPrice,Data.Bars); ArrayInitialize(bottomPrice,0); double top=DBL_MIN; double bottom=DBL_MAX; for(int bar=1; bartop) top=Data.High[bar-1]; if(Data.Low[bar-1]adBasePrice[bar-1]) adCMO1[bar]=adBasePrice[bar]-adBasePrice[bar-1]; if(adBasePrice[bar]Data.High[bar-1] && dValueData.Open[bar]) || // It jumps above the current bar (Data.Close[bar - 1] < dValue && dValue < Data.Open[bar]) || // Positive gap (Data.Close[bar - 1] > dValue && dValue > Data.Open[bar])) // Negative gap dTempVal=Data.Open[bar]; Component[1].Value[bar]=dTempVal; } } else { ArrayResize(Component[1].Value,Data.Bars); Component[1].FirstBar=firstBar; ArrayResize(Component[2].Value,Data.Bars); Component[2].FirstBar=firstBar; } ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "MA Value"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value,adMA); if(SlotType==SlotTypes_Open) { Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType_OpenPrice; } else if(SlotType==SlotTypes_OpenFilter) { Component[1].DataType = IndComponentType_AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType_AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if(SlotType==SlotTypes_Close) { Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType_ClosePrice; } else if(SlotType==SlotTypes_CloseFilter) { Component[1].DataType = IndComponentType_ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType_ForceCloseShort; Component[2].CompName = "Close out short position"; } if(SlotType==SlotTypes_OpenFilter || SlotType==SlotTypes_CloseFilter) { if(ListParam[0].Text=="The Vidya Moving Average rises") IndicatorRisesLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The Vidya Moving Average falls") IndicatorFallsLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the Vidya Moving Average") BarOpensAboveIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the Vidya Moving Average") BarOpensBelowIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the Vidya Moving Average after opening below it") BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the Vidya Moving Average after opening above it") BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The position opens above the Vidya Moving Average") { Component[0].PosPriceDependence=PositionPriceDependence_BuyHigherSellLower; Component[0].UsePreviousBar=previous; Component[1].DataType=IndComponentType_Other; Component[1].ShowInDynInfo=false; Component[2].DataType=IndComponentType_Other; Component[2].ShowInDynInfo=false; } else if(ListParam[0].Text=="The position opens below the Vidya Moving Average") { Component[0].PosPriceDependence=PositionPriceDependence_BuyLowerSelHigher; Component[0].UsePreviousBar=previous; Component[1].DataType=IndComponentType_Other; Component[1].ShowInDynInfo=false; Component[2].DataType=IndComponentType_Other; Component[2].ShowInDynInfo=false; } else if(ListParam[0].Text=="The bar closes below the Vidya Moving Average") BarClosesBelowIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar closes above the Vidya Moving Average") BarClosesAboveIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); } } //+------------------------------------------------------------------+ class IndicatorManager { public: Indicator *CreateIndicator(string indicatorName,SlotTypes slotType); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Indicator *IndicatorManager::CreateIndicator(string indicatorName,SlotTypes slotType) { if(indicatorName == "Hourly High Low") return new HourlyHighLow(slotType); if(indicatorName == "MA Oscillator") return new MAOscillator(slotType); if(indicatorName == "Parabolic SAR") return new ParabolicSAR(slotType); if(indicatorName == "ROC MA Oscillator") return new ROCMAOscillator(slotType); if(indicatorName == "Top Bottom Price") return new TopBottomPrice(slotType); if (indicatorName == "Vidya Moving Average") return new VidyaMovingAverage(slotType); return NULL; } //+------------------------------------------------------------------+ class IndicatorSlot { public: // Constructors IndicatorSlot(); ~IndicatorSlot(); // Properties int SlotNumber; SlotTypes SlotType; string IndicatorName; string LogicalGroup; int SignalShift; int SignalRepeat; string IndicatorSymbol; DataPeriod IndicatorPeriod; Indicator *IndicatorPointer; // Methods bool GetUsePreviousBarValue(void); string LogicalGroupToString(void); string AdvancedParamsToString(void); string GetIndicatorSymbol(string baseSymbol); DataPeriod GetIndicatorPeriod(DataPeriod basePeriod); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ IndicatorSlot::IndicatorSlot(void) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ IndicatorSlot::~IndicatorSlot(void) { if(CheckPointer(IndicatorPointer)==POINTER_DYNAMIC) delete IndicatorPointer; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IndicatorSlot::GetUsePreviousBarValue(void) { for(int i=0; i0) Slot[i].IndicatorPointer.ShiftSignal(Slot[i].SignalShift); if(Slot[i].SignalRepeat>0) Slot[i].IndicatorPointer.RepeatSignal(Slot[i].SignalRepeat); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Strategy::IsUsingLogicalGroups() { bool isUsingGroups=false; for(int slot=0; slot1) return (true); } return (false); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Strategy::GetDefaultGroup(int slotNumber) { string group=""; SlotTypes slotType=GetSlotType(slotNumber); if(slotType==SlotTypes_OpenFilter) { bool isDefault=Slot[slotNumber].IndicatorPointer.IsDeafultGroupAll || Slot[slotNumber].IndicatorPointer.IsDefaultGroupAll; group=isDefault ? "All" : "A"; } else if(slotType==SlotTypes_CloseFilter) { int index=slotNumber-CloseSlotNumber()-1; group=IntegerToString('a'+index); } return (group); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Strategy::DynamicInfoInitArrays(string ¶ms[],string &values[]) { ArrayResize(params,200); ArrayResize(values,200); for(int i=0; i<200; i++) { params[i] = ""; values[i] = ""; } int index=-2; for(int slot=0; slot 0; strategy.Description = "Exported on 20/12/2019 from Forex Strategy Builder Professional, v3.8.8"; strategy.RecommendedBars = 1000; strategy.FirstBar = 28; strategy.MinBarsRequired = 29; strategy.PermanentSL = Stop_Loss; strategy.UsePermanentSL = Stop_Loss > 0; strategy.PermanentSLType = PermanentProtectionType_Relative; strategy.PermanentTP = Take_Profit; strategy.UsePermanentTP = Take_Profit > 0; strategy.PermanentTPType = PermanentProtectionType_Relative; strategy.BreakEven = Break_Even; strategy.UseBreakEven = Break_Even > 0; strategy.Slot[0].IndicatorName = "Vidya Moving Average"; strategy.Slot[0].SlotType = SlotTypes_Open; strategy.Slot[0].SignalShift = 0; strategy.Slot[0].SignalRepeat = 0; strategy.Slot[0].IndicatorPeriod = DataPeriod_M1; strategy.Slot[0].IndicatorSymbol = ""; strategy.Slot[0].LogicalGroup = ""; strategy.Slot[0].IndicatorPointer = indicatorManager.CreateIndicator("Vidya Moving Average", SlotTypes_Open); strategy.Slot[0].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[0].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[0].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[0].IndicatorPointer.ListParam[0].Text = "Enter the market at the Vidya Moving Average"; strategy.Slot[0].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[0].IndicatorPointer.ListParam[2].Caption = "Base price"; strategy.Slot[0].IndicatorPointer.ListParam[2].Index = 0; strategy.Slot[0].IndicatorPointer.ListParam[2].Text = "Open"; strategy.Slot[0].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[0].IndicatorPointer.NumParam[0].Caption = "Period"; strategy.Slot[0].IndicatorPointer.NumParam[0].Value = Slot0IndParam0; strategy.Slot[0].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[0].IndicatorPointer.NumParam[1].Caption = "Smooth"; strategy.Slot[0].IndicatorPointer.NumParam[1].Value = Slot0IndParam1; strategy.Slot[0].IndicatorPointer.CheckParam[0].Enabled = true; strategy.Slot[0].IndicatorPointer.CheckParam[0].Caption = "Use previous bar value"; strategy.Slot[0].IndicatorPointer.CheckParam[0].Checked = false; strategy.Slot[1].IndicatorName = "Top Bottom Price"; strategy.Slot[1].SlotType = SlotTypes_OpenFilter; strategy.Slot[1].SignalShift = 0; strategy.Slot[1].SignalRepeat = 0; strategy.Slot[1].IndicatorPeriod = DataPeriod_M1; strategy.Slot[1].IndicatorSymbol = ""; strategy.Slot[1].LogicalGroup = "A"; strategy.Slot[1].IndicatorPointer = indicatorManager.CreateIndicator("Top Bottom Price", SlotTypes_OpenFilter); strategy.Slot[1].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[1].IndicatorPointer.ListParam[0].Index = 7; strategy.Slot[1].IndicatorPointer.ListParam[0].Text = "The position opens above the bottom price"; strategy.Slot[1].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[1].Caption = "Base price"; strategy.Slot[1].IndicatorPointer.ListParam[1].Index = 0; strategy.Slot[1].IndicatorPointer.ListParam[1].Text = "High & Low"; strategy.Slot[1].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[2].Caption = "Base period"; strategy.Slot[1].IndicatorPointer.ListParam[2].Index = 3; strategy.Slot[1].IndicatorPointer.ListParam[2].Text = "Previous month"; strategy.Slot[1].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[0].Caption = "Vertical shift"; strategy.Slot[1].IndicatorPointer.NumParam[0].Value = Slot1IndParam0; strategy.Slot[2].IndicatorName = "MA Oscillator"; strategy.Slot[2].SlotType = SlotTypes_OpenFilter; strategy.Slot[2].SignalShift = 0; strategy.Slot[2].SignalRepeat = 0; strategy.Slot[2].IndicatorPeriod = DataPeriod_M1; strategy.Slot[2].IndicatorSymbol = ""; strategy.Slot[2].LogicalGroup = "A"; strategy.Slot[2].IndicatorPointer = indicatorManager.CreateIndicator("MA Oscillator", SlotTypes_OpenFilter); strategy.Slot[2].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[2].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[2].IndicatorPointer.ListParam[0].Index = 3; strategy.Slot[2].IndicatorPointer.ListParam[0].Text = "MA Oscillator is lower than the Level line"; strategy.Slot[2].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[2].IndicatorPointer.ListParam[1].Caption = "Smoothing method"; strategy.Slot[2].IndicatorPointer.ListParam[1].Index = 1; strategy.Slot[2].IndicatorPointer.ListParam[1].Text = "Weighted"; strategy.Slot[2].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[2].IndicatorPointer.ListParam[2].Caption = "Base price"; strategy.Slot[2].IndicatorPointer.ListParam[2].Index = 3; strategy.Slot[2].IndicatorPointer.ListParam[2].Text = "Close"; strategy.Slot[2].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[0].Caption = "Fast MA period"; strategy.Slot[2].IndicatorPointer.NumParam[0].Value = Slot2IndParam0; strategy.Slot[2].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[1].Caption = "Slow MA period"; strategy.Slot[2].IndicatorPointer.NumParam[1].Value = Slot2IndParam1; strategy.Slot[2].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[2].Caption = "Level"; strategy.Slot[2].IndicatorPointer.NumParam[2].Value = Slot2IndParam2; strategy.Slot[2].IndicatorPointer.CheckParam[0].Enabled = true; strategy.Slot[2].IndicatorPointer.CheckParam[0].Caption = "Use previous bar value"; strategy.Slot[2].IndicatorPointer.CheckParam[0].Checked = true; strategy.Slot[3].IndicatorName = "Parabolic SAR"; strategy.Slot[3].SlotType = SlotTypes_OpenFilter; strategy.Slot[3].SignalShift = 0; strategy.Slot[3].SignalRepeat = 0; strategy.Slot[3].IndicatorPeriod = DataPeriod_M1; strategy.Slot[3].IndicatorSymbol = ""; strategy.Slot[3].LogicalGroup = "A"; strategy.Slot[3].IndicatorPointer = indicatorManager.CreateIndicator("Parabolic SAR", SlotTypes_OpenFilter); strategy.Slot[3].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[3].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[3].IndicatorPointer.ListParam[0].Text = "The price is higher than the PSAR value"; strategy.Slot[3].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.NumParam[0].Caption = "Starting AF"; strategy.Slot[3].IndicatorPointer.NumParam[0].Value = Slot3IndParam0; strategy.Slot[3].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[3].IndicatorPointer.NumParam[1].Caption = "Increment"; strategy.Slot[3].IndicatorPointer.NumParam[1].Value = Slot3IndParam1; strategy.Slot[3].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[3].IndicatorPointer.NumParam[2].Caption = "Maximum AF"; strategy.Slot[3].IndicatorPointer.NumParam[2].Value = Slot3IndParam2; strategy.Slot[4].IndicatorName = "ROC MA Oscillator"; strategy.Slot[4].SlotType = SlotTypes_OpenFilter; strategy.Slot[4].SignalShift = 0; strategy.Slot[4].SignalRepeat = 0; strategy.Slot[4].IndicatorPeriod = DataPeriod_M1; strategy.Slot[4].IndicatorSymbol = ""; strategy.Slot[4].LogicalGroup = "A"; strategy.Slot[4].IndicatorPointer = indicatorManager.CreateIndicator("ROC MA Oscillator", SlotTypes_OpenFilter); strategy.Slot[4].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[4].IndicatorPointer.ListParam[0].Index = 1; strategy.Slot[4].IndicatorPointer.ListParam[0].Text = "ROC MA Oscillator falls"; strategy.Slot[4].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[1].Caption = "Smoothing method"; strategy.Slot[4].IndicatorPointer.ListParam[1].Index = 0; strategy.Slot[4].IndicatorPointer.ListParam[1].Text = "Simple"; strategy.Slot[4].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[2].Caption = "Signal line method"; strategy.Slot[4].IndicatorPointer.ListParam[2].Index = 3; strategy.Slot[4].IndicatorPointer.ListParam[2].Text = "Smoothed"; strategy.Slot[4].IndicatorPointer.ListParam[3].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[3].Caption = "Base price"; strategy.Slot[4].IndicatorPointer.ListParam[3].Index = 6; strategy.Slot[4].IndicatorPointer.ListParam[3].Text = "Weighted"; strategy.Slot[4].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.NumParam[0].Caption = "ROC period"; strategy.Slot[4].IndicatorPointer.NumParam[0].Value = Slot4IndParam0; strategy.Slot[4].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[4].IndicatorPointer.NumParam[1].Caption = "Signal line period"; strategy.Slot[4].IndicatorPointer.NumParam[1].Value = Slot4IndParam1; strategy.Slot[4].IndicatorPointer.CheckParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.CheckParam[0].Caption = "Use previous bar value"; strategy.Slot[4].IndicatorPointer.CheckParam[0].Checked = true; strategy.Slot[5].IndicatorName = "Hourly High Low"; strategy.Slot[5].SlotType = SlotTypes_Close; strategy.Slot[5].SignalShift = 0; strategy.Slot[5].SignalRepeat = 0; strategy.Slot[5].IndicatorPeriod = DataPeriod_M1; strategy.Slot[5].IndicatorSymbol = ""; strategy.Slot[5].LogicalGroup = ""; strategy.Slot[5].IndicatorPointer = indicatorManager.CreateIndicator("Hourly High Low", SlotTypes_Close); strategy.Slot[5].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[5].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[5].IndicatorPointer.ListParam[0].Index = 1; strategy.Slot[5].IndicatorPointer.ListParam[0].Text = "Exit long at the hourly low"; strategy.Slot[5].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[5].IndicatorPointer.ListParam[1].Caption = "Base price"; strategy.Slot[5].IndicatorPointer.ListParam[1].Index = 0; strategy.Slot[5].IndicatorPointer.ListParam[1].Text = "High and Low"; strategy.Slot[5].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[0].Caption = "Start hour (incl.)"; strategy.Slot[5].IndicatorPointer.NumParam[0].Value = Slot5IndParam0; strategy.Slot[5].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[1].Caption = "Start minutes (incl.)"; strategy.Slot[5].IndicatorPointer.NumParam[1].Value = Slot5IndParam1; strategy.Slot[5].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[2].Caption = "End hour (excl.)"; strategy.Slot[5].IndicatorPointer.NumParam[2].Value = Slot5IndParam2; strategy.Slot[5].IndicatorPointer.NumParam[3].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[3].Caption = "End minutes (excl.)"; strategy.Slot[5].IndicatorPointer.NumParam[3].Value = Slot5IndParam3; strategy.Slot[5].IndicatorPointer.NumParam[4].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[4].Caption = "Vertical shift"; strategy.Slot[5].IndicatorPointer.NumParam[4].Value = Slot5IndParam4; delete indicatorManager; return strategy; } //+------------------------------------------------------------------+ #define OP_FLAT -1 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Position { public: // Constructors Position(void); // Properties int PosType; PosDirection Direction; double Lots; datetime OpenTime; double OpenPrice; double StopLossPrice; double TakeProfitPrice; double Profit; double Commission; long Ticket; string PosComment; // Methods string ToString(); void SetPositionInfo(string &positionInfo[]); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Position::Position(void) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Position::ToString() { if(PosType==OP_FLAT) return ("Position: Flat"); string text = "Position: " + "Time=" + TimeToString(OpenTime,TIME_SECONDS) +", "+ "Type=" + (PosType==OP_BUY ? "Long" : "Short") +", "+ "Lots=" + DoubleToString(Lots,2) +", "+ "Price=" + DoubleToString(OpenPrice,_Digits) +", "+ "StopLoss=" + DoubleToString(StopLossPrice,_Digits) +", "+ "TakeProfit=" + DoubleToString(TakeProfitPrice,_Digits) +", "+ "Commission=" + DoubleToString(Commission,2) +", "+ "Profit=" + DoubleToString(Profit,2); if(PosComment!="") text+=", \""+PosComment+"\""; return (text); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Position::SetPositionInfo(string &positionInfo[]) { if(PosType==OP_FLAT) { positionInfo[0] = "Position: Flat"; positionInfo[1] = "."; } else { positionInfo[0]=StringFormat("Position: %s %.2f at %s, Profit %.2f", (PosType==OP_BUY) ? "Long" : "Short", Lots, DoubleToString(OpenPrice,_Digits), Profit); positionInfo[1]=StringFormat("Stop Loss: %s, Take Profit: %s", DoubleToString(StopLossPrice,_Digits), DoubleToString(TakeProfitPrice,_Digits)); } } //+------------------------------------------------------------------+ class Logger { int logLines; int fileHandle; public: string GetLogFileName(string symbol,int dataPeriod,int expertMagic); int CreateLogFile(string fileName); void WriteLogLine(string text); void WriteNewLogLine(string text); void WriteLogRequest(string text,string request); bool IsLogLinesLimitReached(int maxLines); void FlushLogFile(void); void CloseLogFile(void); int CloseExpert(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Logger::GetLogFileName(string symbol,int dataPeriod,int expertMagic) { string time=TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS); StringReplace(time,":",""); StringReplace(time," ","_"); string rnd=IntegerToString(MathRand()); string fileName=symbol+"_"+IntegerToString(dataPeriod)+"_"+ IntegerToString(expertMagic)+"_"+time+"_"+rnd+".log"; return (fileName); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int Logger::CreateLogFile(string fileName) { logLines=0; int handle=FileOpen(fileName,FILE_CSV|FILE_WRITE,","); if(handle>0) fileHandle=handle; else Print("CreateFile: Error while creating log file!"); return (handle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteLogLine(string text) { if(fileHandle <= 0) return; FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text); logLines++; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteNewLogLine(string text) { if(fileHandle <= 0) return; FileWrite(fileHandle,""); FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text); logLines+=2; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteLogRequest(string text,string request) { if(fileHandle <= 0) return; FileWrite(fileHandle,"\n"+text); FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),request); logLines+=3; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::FlushLogFile() { if(fileHandle <= 0) return; FileFlush(fileHandle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::CloseLogFile() { if(fileHandle <= 0) return; WriteNewLogLine(StringFormat("%s Closed.",MQLInfoString(MQL_PROGRAM_NAME))); FileClose(fileHandle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Logger::IsLogLinesLimitReached(int maxLines) { return (logLines > maxLines); } //+------------------------------------------------------------------+ class ActionTrade; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class StrategyTrader { private: ActionTrade *actionTrade; Strategy *strategy; DataMarket *market; double epsilon; bool isEnteredLong; bool isEnteredShort; datetime timeLastEntryBar; datetime barOpenTimeForLastCloseTick; StrategyPriceType openStrPriceType; StrategyPriceType closeStrPriceType; int nBarExit; ExecutionTime openTimeExec; ExecutionTime closeTimeExec; bool useLogicalGroups; DictStringBool *groupsAllowLong; DictStringBool *groupsAllowShort; ListString *openingLogicGroups; ListString *closingLogicGroups; PosDirection GetNewPositionDirection(OrderDirection ordDir,double ordLots,PosDirection posDir,double posLots); TradeDirection AnalyzeEntryPrice(void); TradeDirection AnalyzeEntryDirection(void); void AnalyzeEntryLogicConditions(string group,double buyPrice,double sellPrice,bool &canOpenLong,bool &canOpenShort); double AnalyzeEntrySize(OrderDirection ordDir,PosDirection &newPosDir); TradeDirection AnalyzeExitPrice(void); double TradingSize(double size); int AccountPercentStopPoint(double percent,double lots); TradeDirection AnalyzeExitDirection(void); TradeDirection ReduceDirectionStatus(TradeDirection baseDirection,TradeDirection direction); TradeDirection IncreaseDirectionStatus(TradeDirection baseDirection,TradeDirection direction); TradeDirection GetClosingDirection(TradeDirection baseDirection,IndComponentType compDataType); int GetStopLossPoints(double lots); int GetTakeProfitPoints(void); void DoEntryTrade(TradeDirection tradeDir); bool DoExitTrade(void); public: // Constructor, deconstructor StrategyTrader(ActionTrade *actTrade); ~StrategyTrader(void); // Methods void OnInit(Strategy *strat,DataMarket *dataMarket); void OnDeinit(); void InitTrade(void); TickType GetTickType(bool isNewBar,int closeAdvance); void CalculateTrade(TickType ticktype); bool IsWrongStopsExecution(void); void ResendWrongStops(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::StrategyTrader(ActionTrade *actTrade) { actionTrade=actTrade; epsilon=0.000001; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::~StrategyTrader(void) { actionTrade = NULL; strategy = NULL; market = NULL; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::OnInit(Strategy *strat,DataMarket *dataMarket) { strategy = strat; market = dataMarket; groupsAllowLong = new DictStringBool(); groupsAllowShort = new DictStringBool(); openingLogicGroups = new ListString(); closingLogicGroups = new ListString(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::OnDeinit(void) { delete groupsAllowLong; delete groupsAllowShort; delete openingLogicGroups; delete closingLogicGroups; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TickType StrategyTrader::GetTickType(bool isNewBar,int closeAdvance) { TickType tickType = TickType_Regular; datetime barCloseTime = market.BarTime + market.Period*60; if(isNewBar) { barOpenTimeForLastCloseTick=-1; tickType=TickType_Open; } if(market.TickServerTime>barCloseTime-closeAdvance) { if(barOpenTimeForLastCloseTick==market.BarTime) { tickType=TickType_AfterClose; } else { barOpenTimeForLastCloseTick=market.BarTime; tickType=isNewBar ? TickType_OpenClose : TickType_Close; } } return (tickType); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::CalculateTrade(TickType ticktype) { // Exift bool closeOk=false; if(closeStrPriceType!=StrategyPriceType_CloseAndReverse && (market.PositionDirection==PosDirection_Short || market.PositionDirection==PosDirection_Long)) { if(ticktype==TickType_Open && closeStrPriceType==StrategyPriceType_Close && openStrPriceType!=StrategyPriceType_Close) { // We have missed close at the previous Bar Close TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) { // we have a missed close Order if(DoExitTrade()) actionTrade.UpdateDataMarket(market); } } else if(((closeStrPriceType==StrategyPriceType_Open) && (ticktype==TickType_Open || ticktype==TickType_OpenClose)) || ((closeStrPriceType==StrategyPriceType_Close) && (ticktype==TickType_Close || ticktype==TickType_OpenClose))) { // Exit at Bar Open or Bar Close. TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) { // Close the current position. closeOk=DoExitTrade(); if(closeOk) actionTrade.UpdateDataMarket(market); } } else if(closeStrPriceType==StrategyPriceType_Close && openStrPriceType!=StrategyPriceType_Close && ticktype==TickType_AfterClose) { // Exit at after close tick. TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) closeOk=DoExitTrade(); // Close the current position. } else if(closeStrPriceType==StrategyPriceType_Indicator) { // Exit at an indicator value. TradeDirection priceReached=AnalyzeExitPrice(); if(priceReached==TradeDirection_Long) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Both) { if(market.PositionDirection==PosDirection_Short) closeOk=DoExitTrade(); // Close a short position. } } else if(priceReached==TradeDirection_Short) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Short || direction==TradeDirection_Both) { if(market.PositionDirection==PosDirection_Long) closeOk=DoExitTrade(); // Close a long position. } } else if(priceReached==TradeDirection_Both) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short || direction==TradeDirection_Both) closeOk=DoExitTrade(); // Close the current position. } } } // Checks if we closed a position successfully. if(closeOk && !(openStrPriceType==StrategyPriceType_Close && ticktype==TickType_Close)) return; // This is to prevent new entry after Bar Closing has been executed. if(closeStrPriceType==StrategyPriceType_Close && ticktype==TickType_AfterClose) return; if(((openStrPriceType==StrategyPriceType_Open) && (ticktype==TickType_Open || ticktype==TickType_OpenClose)) || ((openStrPriceType==StrategyPriceType_Close) && (ticktype==TickType_Close || ticktype==TickType_OpenClose))) { // Entry at Bar Open or Bar Close. TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short) DoEntryTrade(direction); } else if(openStrPriceType==StrategyPriceType_Indicator) { // Entry at an indicator value. TradeDirection priceReached=AnalyzeEntryPrice(); if(priceReached==TradeDirection_Long) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Both) DoEntryTrade(TradeDirection_Long); } else if(priceReached==TradeDirection_Short) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Short || direction==TradeDirection_Both) DoEntryTrade(TradeDirection_Short); } else if(priceReached==TradeDirection_Both) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short) DoEntryTrade(direction); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ PosDirection StrategyTrader::GetNewPositionDirection(OrderDirection ordDir,double ordLots, PosDirection posDir,double posLots) { if(ordDir!=OrderDirection_Buy && ordDir!=OrderDirection_Sell) return (PosDirection_None); PosDirection currentDir=posDir; double currentLots=posLots; switch(currentDir) { case PosDirection_Long: if(ordDir==OrderDirection_Buy) return (PosDirection_Long); if(currentLots>ordLots+epsilon) return (PosDirection_Long); return (currentLots < ordLots - epsilon ? PosDirection_Short : PosDirection_None); case PosDirection_Short: if(ordDir==OrderDirection_Sell) return (PosDirection_Short); if(currentLots>ordLots+epsilon) return (PosDirection_Short); return (currentLots < ordLots - epsilon ? PosDirection_Long : PosDirection_None); } return (ordDir == OrderDirection_Buy ? PosDirection_Long : PosDirection_Short); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::InitTrade() { openTimeExec=strategy.Slot[0].IndicatorPointer.ExecTime; openStrPriceType=StrategyPriceType_Unknown; if(openTimeExec==ExecutionTime_AtBarOpening) openStrPriceType=StrategyPriceType_Open; else if(openTimeExec==ExecutionTime_AtBarClosing) openStrPriceType=StrategyPriceType_Close; else openStrPriceType=StrategyPriceType_Indicator; closeTimeExec=strategy.Slot[strategy.CloseSlotNumber()].IndicatorPointer.ExecTime; closeStrPriceType=StrategyPriceType_Unknown; if(closeTimeExec==ExecutionTime_AtBarOpening) closeStrPriceType=StrategyPriceType_Open; else if(closeTimeExec==ExecutionTime_AtBarClosing) closeStrPriceType=StrategyPriceType_Close; else if(closeTimeExec==ExecutionTime_CloseAndReverse) closeStrPriceType=StrategyPriceType_CloseAndReverse; else closeStrPriceType=StrategyPriceType_Indicator; useLogicalGroups=strategy.IsUsingLogicalGroups(); if(useLogicalGroups) { strategy.Slot[0].LogicalGroup="All"; strategy.Slot[strategy.CloseSlotNumber()].LogicalGroup="All"; for(int slot=0; slotoldPrice+epsilon && buyPricebasePrice-epsilon && buyPriceoldPrice+epsilon && sellPricebasePrice-epsilon && sellPrice=TimeDayOfWeek(timeLastEntryBar) && market.BarTimeepsilon; bool canOpenShort=sellPrice>epsilon; if(useLogicalGroups) { for(int i=0; i1 && key!="All") || groupsAllowLong.Count()==1) groupLongEntry=groupLongEntry || value; } bool groupShortEntry=false; for(int i=0; i1 && key!="All") || groupsAllowShort.Count()==1) groupShortEntry=groupShortEntry || value; } canOpenLong=canOpenLong && groupLongEntry && groupsAllowLong.Value("All"); canOpenShort=canOpenShort && groupShortEntry && groupsAllowShort.Value("All"); } else { AnalyzeEntryLogicConditions("A",buyPrice,sellPrice,canOpenLong,canOpenShort); } TradeDirection direction=TradeDirection_None; if(canOpenLong && canOpenShort) direction=TradeDirection_Both; else if(canOpenLong) direction=TradeDirection_Long; else if(canOpenShort) direction=TradeDirection_Short; return (direction); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::AnalyzeEntryLogicConditions(string group,double buyPrice,double sellPrice, bool &canOpenLong,bool &canOpenShort) { for(int slotIndex=0; slotIndex<=strategy.CloseSlotNumber(); slotIndex++) { if(useLogicalGroups && strategy.Slot[slotIndex].LogicalGroup != group && strategy.Slot[slotIndex].LogicalGroup != "All") continue; for(int i=0; i epsilon) { switch(component.PosPriceDependence) { case PositionPriceDependence_PriceBuyHigher: canOpenLong=canOpenLong && buyPrice>indicatorValue+epsilon; break; case PositionPriceDependence_PriceBuyLower: canOpenLong=canOpenLong && buyPriceindicatorValue+epsilon; break; case PositionPriceDependence_PriceSellLower: canOpenShort=canOpenShort && sellPrice indicatorValue + epsilon; canOpenShort = canOpenShort && sellPrice < indicatorValue - epsilon; break; case PositionPriceDependence_BuyLowerSelHigher: // Deprecated case PositionPriceDependence_BuyLowerSellHigher: canOpenLong = canOpenLong && buyPrice < indicatorValue - epsilon; canOpenShort = canOpenShort && sellPrice > indicatorValue + epsilon; break; } } else { canOpenLong = false; canOpenShort = false; } } component=NULL; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double StrategyTrader::AnalyzeEntrySize(OrderDirection ordDir,PosDirection &newPosDir) { double size=0; PosDirection posDir=market.PositionDirection; // Orders modification on a fly // Checks whether we are on the market if(posDir==PosDirection_Long || posDir==PosDirection_Short) { // We are on the market and have Same Dir Signal if((ordDir==OrderDirection_Buy && posDir==PosDirection_Long) || (ordDir==OrderDirection_Sell && posDir==PosDirection_Short)) { size=0; newPosDir=posDir; if(market.PositionLots+TradingSize(strategy.AddingLots)< strategy.MaxOpenLots+market.LotStep/2) { switch(strategy.SameSignalAction) { case SameDirSignalAction_Add: size=TradingSize(strategy.AddingLots); break; case SameDirSignalAction_Winner: if(market.PositionProfit>epsilon) size=TradingSize(strategy.AddingLots); break; case SameDirSignalAction_Loser: if(market.PositionProfit<-epsilon) size=TradingSize(strategy.AddingLots); break; } } } else if((ordDir==OrderDirection_Buy && posDir==PosDirection_Short) || (ordDir==OrderDirection_Sell && posDir==PosDirection_Long)) { // In case of an Opposite Dir Signal switch(strategy.OppSignalAction) { case OppositeDirSignalAction_Reduce: if(market.PositionLots>TradingSize(strategy.ReducingLots)) { // Reducing size=TradingSize(strategy.ReducingLots); newPosDir=posDir; } else { // Closing size=market.PositionLots; newPosDir=PosDirection_Closed; } break; case OppositeDirSignalAction_Close: size=market.PositionLots; newPosDir=PosDirection_Closed; break; case OppositeDirSignalAction_Reverse: size=market.PositionLots+TradingSize(strategy.EntryLots); newPosDir=(posDir==PosDirection_Long) ? PosDirection_Short : PosDirection_Long; break; case OppositeDirSignalAction_Nothing: size=0; newPosDir=posDir; break; } } } else { // We are square on the market size=TradingSize(strategy.EntryLots); if(strategy.UseMartingale && market.ConsecutiveLosses>0) { double correctedAmount=size*MathPow(strategy.MartingaleMultiplier,market.ConsecutiveLosses); double normalizedAmount=actionTrade.NormalizeEntrySize(correctedAmount); size=MathMax(normalizedAmount,market.MinLot); } size=MathMin(size,strategy.MaxOpenLots); newPosDir=(ordDir==OrderDirection_Buy) ? PosDirection_Long : PosDirection_Short; } return (size); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::AnalyzeExitPrice() { IndicatorSlot *slot=strategy.Slot[strategy.CloseSlotNumber()]; // Searching the exit price in the exit indicator slot. double buyPrice=0; double sellPrice=0; for(int i=0; iepsilon; bool canCloseShort=buyPrice>epsilon; // Check if the closing price was reached. if(canCloseLong) { canCloseLong=(sellPrice>market.OldBid+epsilon && sellPricemarket.Bid-epsilon); } if(canCloseShort) { canCloseShort=(buyPrice>market.OldBid+epsilon && buyPricemarket.Bid-epsilon); } // Determine the trading direction. TradeDirection direction=TradeDirection_None; if(canCloseLong && canCloseShort) direction=TradeDirection_Both; else if(canCloseLong) direction=TradeDirection_Short; else if(canCloseShort) direction=TradeDirection_Long; slot=NULL; return (direction); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::AnalyzeExitDirection() { int closeSlot=strategy.CloseSlotNumber(); if(closeTimeExec==ExecutionTime_AtBarClosing) for(int i=0; i0 && (market.PositionOpenTime+(nBarExit *((int) market.Period*60))0) slotDirection=GetClosingDirection(slotDirection,strategy.Slot[slot].IndicatorPointer.Component[c].DataType); } groupDirection=ReduceDirectionStatus(groupDirection,slotDirection); } } direction=IncreaseDirectionStatus(direction,groupDirection); } } else { // Search close filters for a closing signal. for(int slot=strategy.CloseSlotNumber()+1; slotepsilon) direction=GetClosingDirection(direction,strategy.Slot[slot].IndicatorPointer.Component[c].DataType); } } } return (direction); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::ReduceDirectionStatus(TradeDirection baseDirection,TradeDirection direction) { if(baseDirection==direction || direction==TradeDirection_Both) return (baseDirection); if(baseDirection==TradeDirection_Both) return (direction); return (TradeDirection_None); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::IncreaseDirectionStatus(TradeDirection baseDirection,TradeDirection direction) { if(baseDirection==direction || direction==TradeDirection_None) return (baseDirection); if(baseDirection==TradeDirection_None) return (direction); return (TradeDirection_Both); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::GetClosingDirection(TradeDirection baseDirection,IndComponentType compDataType) { TradeDirection newDirection=baseDirection; if(compDataType==IndComponentType_ForceClose) { newDirection=TradeDirection_Both; } else if(compDataType==IndComponentType_ForceCloseShort) { if(baseDirection == TradeDirection_None) newDirection = TradeDirection_Long; else if(baseDirection==TradeDirection_Short) newDirection=TradeDirection_Both; } else if(compDataType==IndComponentType_ForceCloseLong) { if(baseDirection == TradeDirection_None) newDirection = TradeDirection_Short; else if(baseDirection==TradeDirection_Long) newDirection=TradeDirection_Both; } return (newDirection); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int StrategyTrader::GetStopLossPoints(double lots) { int indStop = INT_MAX; bool isIndStop = true; int closeSlot = strategy.CloseSlotNumber(); string name=strategy.Slot[closeSlot].IndicatorName; if(name=="Account Percent Stop") indStop=AccountPercentStopPoint(strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value,lots); else if(name== "ATR Stop") indStop =(int) MathRound(strategy.Slot[closeSlot].IndicatorPointer.Component[0].GetLastValue()/market.Point); else if(name== "Stop Loss"|| name == "Stop Limit") indStop =(int) strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value; else if(name== "Trailing Stop"|| name == "Trailing Stop Limit") indStop =(int) strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value; else isIndStop=false; int permStop = strategy.UsePermanentSL ? strategy.PermanentSL : INT_MAX; int stopLoss = 0; if(isIndStop || strategy.UsePermanentSL) { stopLoss=MathMin(indStop,permStop); if(stopLoss=maxRetry) { market.WrongStopLoss = 0; market.WrongTakeProf = 0; market.WrongStopsRetry = 0; return (false); } bool isWrongStop=(market.WrongStopLoss>0 && market.PositionStopLoss0 && market.PositionTakeProfit0) { if(market.PositionDirection==PosDirection_Long) stopLossPrice=market.Bid-stopLoss*market.Point; else if(market.PositionDirection==PosDirection_Short) stopLossPrice=market.Ask+stopLoss*market.Point; } double takeProfitPrice=0; int takeProfit=market.WrongTakeProf; if(takeProfit>0) { if(market.PositionDirection==PosDirection_Long) takeProfitPrice=market.Bid+takeProfit*market.Point; else if(market.PositionDirection==PosDirection_Short) takeProfitPrice=market.Ask-takeProfit*market.Point; } bool isSucess=actionTrade.ModifyPosition(stopLossPrice,takeProfitPrice); if(isSucess) { market.WrongStopLoss = 0; market.WrongTakeProf = 0; market.WrongStopsRetry = 0; } else { market.WrongStopsRetry++; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double StrategyTrader::TradingSize(double size) { if(strategy.UseAccountPercentEntry) size=(size/100)*market.AccountEquity/market.MarginRequired; if(size>strategy.MaxOpenLots) size=strategy.MaxOpenLots; return (actionTrade.NormalizeEntrySize(size)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int StrategyTrader::AccountPercentStopPoint(double percent,double lots) { double balance = market.AccountBalance; double moneyrisk = balance * percent / 100; double spread = market.Spread; double tickvalue = market.TickValue; double stoploss = moneyrisk / (lots * tickvalue) - spread; return ((int) MathRound(stoploss)); } //+------------------------------------------------------------------+ #define TRADE_RETRY_COUNT 4 #define TRADE_RETRY_WAIT 100 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class ActionTrade { private: double epsilon; // Fields Strategy *strategy; DataSet *dataSet[]; DataMarket *dataMarket; Position *position; Logger *logger; StrategyTrader *strategyTrader; ENUM_ORDER_TYPE_FILLING orderFillingType; // Properties int lastError; double pipsValue; int pipsPoint; int stopLevel; datetime barTime; datetime barHighTime; datetime barLowTime; double barHighPrice; double barLowPrice; int trailingStop; TrailingStopMode trailingMode; int breakEven; int consecutiveLosses; string dynamicInfoParams[]; string dynamicInfoValues[]; // Methods bool CheckEnvironment(int minDataBars); bool CheckChartBarsCount(int minDataBars); int FindBarsCountNeeded(int minDataBars); int SetAggregatePosition(Position *pos); void UpdateDataSet(DataSet *data,int maxBars); bool IsTradeContextFree(void); void ActivateProtectionMinAccount(void); void CloseExpert(void); ENUM_ORDER_TYPE_FILLING GetOrderFillingType(void); // Trading methods double GetTakeProfitPrice(int type,int takeProfit); double GetStopLossPrice(int type,int stopLoss); double CorrectTakeProfitPrice(int type,double takeProfitPrice); double CorrectStopLossPrice(int type,double stopLossPrice); double NormalizeEntryPrice(double price); void SetMaxStopLoss(void); void SetBreakEvenStop(void); void SetTrailingStop(bool isNewBar); void SetTrailingStopBarMode(void); void SetTrailingStopTickMode(void); void DetectPositionClosing(void); public: // Constructor, deconstructor ActionTrade(void); ~ActionTrade(void); // Properties double EntryAmount; double MaximumAmount; double AddingAmount; double ReducingAmount; string OrderComment; int MinDataBars; int ProtectionMinAccount; int ProtectionMaxStopLoss; bool SeparateSLTP; bool WriteLogFile; int TrailingStopMovingStep; int MaxLogLinesInFile; int BarCloseAdvance; // Methods int OnInit(void); void OnTick(void); void OnTrade(void); void OnDeinit(const int reason); void UpdateDataMarket(DataMarket *market); double NormalizeEntrySize(double size); bool ManageOrderSend(int type,double lots,int stopLoss,int takeProfit, TrailingStopMode trlMode,int trlStop,int brkEven); bool ModifyPosition(double stopLossPrice,double takeProfitPrice); bool CloseCurrentPosition(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::ActionTrade(void) { epsilon = 0.000001; position = new Position(); logger = new Logger(); strategyTrader = new StrategyTrader(GetPointer(this)); orderFillingType = GetOrderFillingType(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::~ActionTrade(void) { if(CheckPointer(position)==POINTER_DYNAMIC) delete position; if(CheckPointer(logger)==POINTER_DYNAMIC) delete logger; if(CheckPointer(strategyTrader)==POINTER_DYNAMIC) delete strategyTrader; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int ActionTrade::OnInit() { dataMarket = new DataMarket(); barHighTime = 0; barLowTime = 0; barHighPrice = 0; barLowPrice = 1000000; string message=StringFormat("%s loaded.",MQLInfoString(MQL_PROGRAM_NAME)); Comment(message); Print(message); if(WriteLogFile) { logger.CreateLogFile(logger.GetLogFileName(_Symbol, _Period, 5)); logger.WriteLogLine(message); logger.WriteLogLine("Entry Amount: " + DoubleToString(EntryAmount, 2) + ", " + "Maximum Amount: " + DoubleToString(MaximumAmount, 2) + ", " + "Adding Amount: " + DoubleToString(AddingAmount, 2) + ", " + "Reducing Amount: " + DoubleToString(ReducingAmount, 2)); logger.WriteLogLine("Protection Min Account: " + IntegerToString(ProtectionMinAccount) + ", " + "Protection Max StopLoss: " + IntegerToString(ProtectionMaxStopLoss)); logger.WriteLogLine("Bar Close Advance: " + IntegerToString(BarCloseAdvance)); logger.FlushLogFile(); } if(_Digits==2 || _Digits==3) pipsValue=0.01; else if(_Digits==4 || _Digits==5) pipsValue=0.0001; else pipsValue=_Digits; if(_Digits==3 || _Digits==5) pipsPoint=10; else pipsPoint=1; stopLevel=(int) SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)+pipsPoint; if(stopLevel<3*pipsPoint) stopLevel=3*pipsPoint; if(ProtectionMaxStopLoss>0 && ProtectionMaxStopLoss0 && AccountInfoDouble(ACCOUNT_EQUITY)0) SetMaxStopLoss(); // Checks if position was closed. DetectPositionClosing(); if(breakEven>0) SetBreakEvenStop(); if(trailingStop>0) SetTrailingStop(isNewBar); SetAggregatePosition(position); if(isNewBar && WriteLogFile) logger.WriteNewLogLine(position.ToString()); if(dataSet[0].Bars>=strategy.MinBarsRequired) { strategy.CalculateStrategy(dataSet); TickType tickType=strategyTrader.GetTickType(isNewBar,BarCloseAdvance); strategyTrader.CalculateTrade(tickType); } // Sends OrderModify on SL/TP errors if(strategyTrader.IsWrongStopsExecution()) strategyTrader.ResendWrongStops(); string accountInfo=StringFormat("%s Balance: %.2f, Equity: %.2f", TimeToString(dataMarket.TickServerTime,TIME_SECONDS), AccountInfoDouble(ACCOUNT_BALANCE), AccountInfoDouble(ACCOUNT_EQUITY)); LabelTextChange(0,"Lbl_pos_0",accountInfo); string positionInfo[2]; position.SetPositionInfo(positionInfo); for(int i=0; i<2; i++) { LabelTextChange(0,"Lbl_pos_"+IntegerToString(i+1),positionInfo[i]); } strategy.DynamicInfoSetValues(dynamicInfoValues); int count = ArraySize(dynamicInfoValues); for(int i = 0; i < count; i++) { string namev="Lbl_val_"+IntegerToString(i); string val=dynamicInfoValues[i]=="" ? "." : dynamicInfoValues[i]; LabelTextChange(0,namev,val); } if(WriteLogFile) { if(logger.IsLogLinesLimitReached(MaxLogLinesInFile)) { logger.CloseLogFile(); logger.CreateLogFile(logger.GetLogFileName(_Symbol, _Period, 5)); } logger.FlushLogFile(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::OnDeinit(const int reason) { strategyTrader.OnDeinit(); if(WriteLogFile) logger.CloseLogFile(); if(CheckPointer(strategy)==POINTER_DYNAMIC) delete strategy; for(int i=0; i=0; i--) { if((ticket=HistoryDealGetTicket(i))>0) { double price = HistoryDealGetDouble(ticket, DEAL_PRICE); long time = HistoryDealGetInteger(ticket, DEAL_TIME); string symbol = HistoryDealGetString(ticket, DEAL_SYMBOL); double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT); if(price>epsilon && time>0 && symbol==_Symbol) { if(profit<-epsilon) maxLosses++; if(profit>epsilon) { consecutiveLosses=maxLosses; break; } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ActionTrade::CheckEnvironment(int minDataBars) { // Checks the count of bars available. if(!CheckChartBarsCount(minDataBars)) return (false); if(MQLInfoInteger(MQL_TESTER)) { SetAggregatePosition(position); return (true); } if(AccountNumber()==0) { Comment("\n You are not logged in. Please login first."); for(int attempt=0; attempt<200; attempt++) { if(AccountNumber()==0) Sleep(300); else break; } if(AccountNumber()==0) return (false); } if(SetAggregatePosition(position)==-1) return (false); return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int ActionTrade::FindBarsCountNeeded(int minDataBars) { int barStep = 50; int minBars = MathMax(minDataBars, 50); int maxBars = MathMax(minBars, 3000); // Initial state int initialBars=MathMax(strategy.MinBarsRequired,minBars); initialBars=MathMax(strategy.FirstBar,initialBars); for(int i=0; i=initialBars+barStep/2 ? roundedInitialBars : roundedInitialBars+barStep; for(int bars=firstTestBars; bars<=maxBars; bars+=barStep) { for(int i=0; iepsilon) { // Reset the test if new tick has arrived. for(int i=0; i epsilon; market.LotSize = (int) SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE); market.StopLevel = (int) SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL); market.Point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); market.TickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); market.MinLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); market.MaxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); market.LotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); market.MarginRequired = SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL); market.Spread = (market.Ask - market.Bid) / market.Point; if(market.MarginRequired=minDataBars; if(isEnoughBars) return (true); string message="\n Cannot load enough bars! The expert needs minimum "+ IntegerToString(minDataBars)+" bars."+ "\n Currently "+IntegerToString(bars)+" bars are loaded."; if(MQLInfoInteger(MQL_TESTER)) message+="\n Please use a custom date period and set the dates properly."; Comment(message); Print(message); return (false); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int ActionTrade::SetAggregatePosition(Position *pos) { pos.PosType = OP_FLAT; pos.Direction = PosDirection_None; pos.OpenTime = D'2050.01.01 00:00'; pos.Lots = 0; pos.OpenPrice = 0; pos.StopLossPrice = 0; pos.TakeProfitPrice = 0; pos.Profit = 0; pos.Commission = 0; pos.Ticket = 0; pos.PosComment = ""; if(!PositionSelect(_Symbol)) return (0); pos.PosType = (int) PositionGetInteger(POSITION_TYPE); pos.Direction = position.PosType == OP_FLAT ? PosDirection_None : position.PosType==OP_BUY ? PosDirection_Long : PosDirection_Short; pos.OpenTime=(datetime) MathMax(PositionGetInteger(POSITION_TIME), PositionGetInteger(POSITION_TIME_UPDATE)); pos.OpenPrice = NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN), _Digits); pos.Lots = NormalizeDouble(PositionGetDouble(POSITION_VOLUME), 2); pos.Profit = NormalizeDouble(PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_COMMISSION),2); pos.Commission=NormalizeDouble(PositionGetDouble(POSITION_COMMISSION),2); pos.StopLossPrice = NormalizeDouble(PositionGetDouble(POSITION_SL), _Digits); pos.TakeProfitPrice = NormalizeDouble(PositionGetDouble(POSITION_TP), _Digits); pos.Ticket = PositionGetInteger(POSITION_TICKET); pos.PosComment = PositionGetString(POSITION_COMMENT); return (1); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ActionTrade::ManageOrderSend(int type,double lots,int stopLoss,int takeProfit, TrailingStopMode trlMode,int trlStop,int brkEven) { trailingMode = trlMode; trailingStop = trlStop; breakEven = brkEven; for(int attempt=0; attemptorderLots) request.position=ticket; // Reducing else if(volume=_Point*breakeven) { if(position.StopLossPrice30*1000) { Print("The waiting limit exceeded!"); return (false); } if(MQL5InfoInteger(MQL5_TRADE_ALLOWED)) return (true); Sleep(100); } return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::ActivateProtectionMinAccount() { if(position.Lots>epsilon) CloseCurrentPosition(); string account = DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2); string message = "\n" + "The account equity (" + account + ") dropped below the minimum allowed ("+ IntegerToString(ProtectionMinAccount)+")."; Comment(message); Print(message); if(WriteLogFile) logger.WriteLogLine(message); Sleep(20*1000); CloseExpert(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::CloseExpert(void) { ExpertRemove(); OnDeinit(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ ENUM_ORDER_TYPE_FILLING ActionTrade::GetOrderFillingType() { const int oftIndex=(int) SymbolInfoInteger(_Symbol,SYMBOL_FILLING_MODE); const ENUM_ORDER_TYPE_FILLING fillType=(ENUM_ORDER_TYPE_FILLING)(oftIndex>0 ? oftIndex-1 : oftIndex); return (fillType); } //+------------------------------------------------------------------+ ActionTrade *actionTrade; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { actionTrade=new ActionTrade(); actionTrade.EntryAmount = Entry_Amount > 77700 ? 0.1 : Entry_Amount; actionTrade.MaximumAmount = Maximum_Amount > 77700 ? 0.1 : Maximum_Amount; actionTrade.AddingAmount = Adding_Amount > 77700 ? 0.1 : Adding_Amount; actionTrade.ReducingAmount = Reducing_Amount > 77700 ? 0.1 : Reducing_Amount; actionTrade.OrderComment = Order_Comment; actionTrade.MinDataBars = Min_Data_Bars; actionTrade.ProtectionMinAccount = Protection_Min_Account; actionTrade.ProtectionMaxStopLoss = Protection_Max_StopLoss; actionTrade.SeparateSLTP = Separate_SL_TP; actionTrade.WriteLogFile = Write_Log_File; actionTrade.TrailingStopMovingStep = TrailingStop_Moving_Step; actionTrade.MaxLogLinesInFile = Max_Log_Lines_in_File; actionTrade.BarCloseAdvance = Bar_Close_Advance; int result=actionTrade.OnInit(); if(result==INIT_SUCCEEDED) actionTrade.OnTick(); return (result); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTick() { if(__symbol!=_Symbol || __period!=_Period) { if(__period>0) { actionTrade.OnDeinit(-1); actionTrade.OnInit(); } __symbol = _Symbol; __period = _Period; } actionTrade.OnTick(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTrade() { actionTrade.OnTrade(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { actionTrade.OnDeinit(reason); if(CheckPointer(actionTrade)==POINTER_DYNAMIC) delete actionTrade; } /*STRATEGY CODE Forex Strategy Builder Professionalv3.8.8feito vendo o video do dono do programaDefault profileFSB Demo dataEURUSD15AddClose1False0.10.10.1False2Exported on 20/12/2019 from Forex Strategy Builder Professional, v3.8.81000402829164510001000Vidya Moving AverageLogic0Enter the market at the Vidya Moving AverageBase price0OpenPeriod21Smooth5Use previous bar valueFalse00M1Top Bottom PriceLogic7The position opens above the bottom priceBase price0High & LowBase period3Previous monthVertical shift0MA OscillatorLogic3MA Oscillator is lower than the Level lineSmoothing method1WeightedBase price3CloseFast MA period13Slow MA period21Level0.0000Use previous bar valueTrue00M1Parabolic SARLogic0The price is higher than the PSAR valueStarting AF0.02Increment0.02Maximum AF2.00ROC MA OscillatorLogic1ROC MA Oscillator fallsSmoothing method0SimpleSignal line method3SmoothedBase price6WeightedROC period10Signal line period14Use previous bar valueTrue00M1Hourly High LowLogic1Exit long at the hourly lowBase price0High and LowStart hour (incl.)0Start minutes (incl.)0End hour (excl.)24End minutes (excl.)0Vertical shift000M1 */ //+------------------------------------------------------------------+