--------------------------------------------------------------------+ //| Copyright: (C) 2016 Forex Software Ltd. | //| Website: http://forexsb.com/ | //| Support: http://forexsb.com/forum/ | //| License: Proprietary under the following circumstances: | //| | //| This code is a part of Forex Strategy Builder. It is free for | //| use as an integral part of Forex Strategy Builder. | //| One can modify it in order to improve the code or to fit it for | //| personal use. This code or any part of it cannot be used in | //| other applications without a permission. | //| The contact information cannot be changed. | //| | //| NO LIABILITY FOR CONSEQUENTIAL DAMAGES | //| | //| In no event shall the author be liable for any damages whatsoever | //| (including, without limitation, incidental, direct, indirect and | //| consequential damages, damages for loss of business profits, | //| business interruption, loss of business information, or other | //| pecuniary loss) arising out of the use or inability to use this | //| product, even if advised of the possibility of such damages. | //+--------------------------------------------------------------------+ #property copyright "Copyright (C) 2016 Forex Software Ltd." #property link "http://forexsb.com" #property version "47.0" #property strict // ----------------------- External variables ----------------------- // static input string StrategyProperties__ = "------------"; // ------ Strategy Properties ------ static input double Entry_Amount = 1; // Amount for a new position [%] static input double Maximum_Amount = 20; // Maximum position amount [lot] static input double Adding_Amount = 1; // Amount to add on addition [%] static input double Reducing_Amount = 1; // Amount to close on reduction [%] input int Stop_Loss = 46; // 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 = "CoralTrend v1"; // ------ Indicator parameters ------ input int Slot0IndParam0 = 207; // Period static input string IndicatorName1 = "Oscillator of MACD"; // ------ Indicator parameters ------ input int Slot1IndParam0 = 20; // MACD1 slow MA input int Slot1IndParam1 = 6; // MACD2 slow MA input int Slot1IndParam2 = 42; // MACD1 fast MA input int Slot1IndParam3 = 170; // MACD2 fast MA input int Slot1IndParam4 = 198; // MACD1 Signal line input int Slot1IndParam5 = 61; // MACD2 Signal line static input string IndicatorName2 = "Moving Average"; // ------ Indicator parameters ------ input int Slot2IndParam0 = 46; // Period input int Slot2IndParam1 = 149; // Shift static input string IndicatorName3 = "RSI MA Oscillator"; // ------ Indicator parameters ------ input int Slot3IndParam0 = 42; // RSI period input int Slot3IndParam1 = 60; // Signal line period static input string IndicatorName4 = "Custom Donchian Channel"; // ------ Indicator parameters ------ input int Slot4IndParam0 = 82; // Period input int Slot4IndParam1 = 42; // Shift static input string ExpertSettings__ = "------------"; // ------ Expert Settings ------ // A unique number of the expert's orders. static input int Expert_Magic = 21081219; // Expert Magic Number // 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; // Separate SL and TP orders // It has 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; // FIFO (First In First Out) forces the expert to close positions starting from // the oldest one. This rule complies with the new NFA regulations. // If you want to close the positions from the newest one (FILO), change the variable to "false". // This doesn't change the normal work of Forex Strategy Builder. bool FIFO_order = true; // 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; //## Import Start 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 }; //+------------------------------------------------------------------+ //## Import Start 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); } //+------------------------------------------------------------------+ //## Import Start 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; }; //+------------------------------------------------------------------+ //## Import Start //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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 MACD : public Indicator { public: MACD(SlotTypes slotType); virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MACD::MACD(SlotTypes slotType) { SlotType = slotType; IndicatorName = "MACD"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = true; IsDiscreteValues = false; IsDefaultGroupAll = false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MACD::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); MAMethod maMethod = (MAMethod) ListParam[1].Index; MAMethod slMethod = (MAMethod) ListParam[3].Index; BasePrice basePrice=(BasePrice) ListParam[2].Index; int slowPeriod = (int) NumParam[0].Value; int fastPeriod = (int) NumParam[1].Value; int signalPeriod=(int) NumParam[2].Value; int previous=CheckParam[0].Checked ? 1 : 0; int firstBar=MathMax(MathMax(slowPeriod,fastPeriod),signalPeriod)+previous+2; double price[]; Price(basePrice,price); double maSlow[]; MovingAverage(slowPeriod,0,maMethod,price,maSlow); double maFast[]; MovingAverage(fastPeriod,0,maMethod,price,maFast); double macd[]; ArrayResize(macd,Data.Bars); ArrayInitialize(macd,0); for(int bar=slowPeriod-1; barprice[bar-1]+Epsilon()) pos[bar]=price[bar]-price[bar-1]; if(price[bar]Epsilon()) rsi[bar]=100 -(100/(1+posMa[bar]/negMa[bar])); else { if(MathAbs(posMa[bar])>Epsilon()) rsi[bar]=100; else rsi[bar]=50; } } // Saving the components ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "RSI"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value,rsi); ArrayResize(Component[1].Value,Data.Bars); Component[1].FirstBar=firstBar; ArrayResize(Component[2].Value,Data.Bars); Component[2].FirstBar=firstBar; // Sets the Component's type 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_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"; } // Calculation of the logic IndicatorLogic indLogic=IndicatorLogic_It_does_not_act_as_a_filter; if(ListParam[0].Text=="RSI rises") indLogic=IndicatorLogic_The_indicator_rises; else if(ListParam[0].Text=="RSI falls") indLogic=IndicatorLogic_The_indicator_falls; else if(ListParam[0].Text=="RSI is higher than the Level line") indLogic=IndicatorLogic_The_indicator_is_higher_than_the_level_line; else if(ListParam[0].Text=="RSI is lower than the Level line") indLogic=IndicatorLogic_The_indicator_is_lower_than_the_level_line; else if(ListParam[0].Text=="RSI crosses the Level line upward") indLogic=IndicatorLogic_The_indicator_crosses_the_level_line_upward; else if(ListParam[0].Text=="RSI crosses the Level line downward") indLogic=IndicatorLogic_The_indicator_crosses_the_level_line_downward; else if(ListParam[0].Text=="RSI changes its direction upward") indLogic=IndicatorLogic_The_indicator_changes_its_direction_upward; else if(ListParam[0].Text=="RSI changes its direction downward") indLogic=IndicatorLogic_The_indicator_changes_its_direction_downward; OscillatorLogic(firstBar,previous,rsi,level,100-level,Component[1],Component[2],indLogic); } //+------------------------------------------------------------------+ class MovingAvrg : public Indicator { public: MovingAvrg(SlotTypes slotType) { SlotType=slotType; IndicatorName="Moving Average"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MovingAvrg::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); MAMethod maMethod =(MAMethod) ListParam[1].Index; BasePrice basePrice=(BasePrice) ListParam[2].Index; int period=(int) NumParam[0].Value; int shift =(int) NumParam[1].Value; int previous=CheckParam[0].Checked ? 1 : 0; if(period==1 && shift==0) { if(basePrice== BasePrice_Open) ExecTime = ExecutionTime_AtBarOpening; else if(basePrice==BasePrice_Close) ExecTime=ExecutionTime_AtBarClosing; } else { ExecTime=ExecutionTime_DuringTheBar; } double price[]; Price(basePrice,price); double movingAverage[]; MovingAverage(period,shift,maMethod,price,movingAverage); int firstBar=period+shift+previous+2; if(SlotType==SlotTypes_Open || SlotType==SlotTypes_Close) { ArrayResize(Component[1].Value,Data.Bars); ArrayInitialize(Component[1].Value,0); for(int bar=firstBar; bar Data.High[bar - 1] && value < Data.Open[bar]) || // The Data.Open price jumps above the indicator (value1 < Data.Low[bar - 1] && value > Data.Open[bar]) || // The Data.Open price jumps below the indicator (Data.Close[bar-1]value && value>Data.Open[bar])) // The Data.Open price is in a negative gap tempVal=Data.Open[bar]; Component[1].Value[bar]=tempVal; // Entry or exit value } } else { ArrayResize(Component[1].Value, Data.Bars); ArrayResize(Component[2].Value, Data.Bars); } ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "MA Value"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value,movingAverage); if(SlotType==SlotTypes_Open) { Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType_OpenPrice; } 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"; } if(SlotType==SlotTypes_Close) { Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType_ClosePrice; } 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=="Moving Average rises") IndicatorRisesLogic(firstBar,previous,movingAverage,Component[1],Component[2]); else if(ListParam[0].Text=="Moving Average falls") IndicatorFallsLogic(firstBar,previous,movingAverage,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above Moving Average") BarOpensAboveIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below Moving Average") BarOpensBelowIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above Moving Average after opening below it") BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar,previous,movingAverage,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below Moving Average after opening above it") BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar,previous,movingAverage,Component[1],Component[2]); else if(ListParam[0].Text=="The position opens above Moving Average") { Component[0].PosPriceDependence=PositionPriceDependence_BuyHigherSellLower; 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 Moving Average") { Component[0].PosPriceDependence=PositionPriceDependence_BuyLowerSellHigher; 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 Moving Average") BarClosesBelowIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]); else if(ListParam[0].Text=="The bar closes above Moving Average") BarClosesAboveIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]); } } //+------------------------------------------------------------------+ class OscillatorofMACD : public Indicator { public: OscillatorofMACD(SlotTypes slotType) { SlotType=slotType; IndicatorName="Oscillator of MACD"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = true; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OscillatorofMACD::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); MACD *macd1=new MACD(SlotType); macd1.ListParam[1].Index = ListParam[1].Index; macd1.ListParam[2].Index = ListParam[2].Index; macd1.ListParam[3].Index = ListParam[3].Index; macd1.NumParam[0].Value = NumParam[0].Value; macd1.NumParam[1].Value = NumParam[2].Value; macd1.NumParam[2].Value = NumParam[4].Value; macd1.CheckParam[0].Checked=CheckParam[0].Checked; macd1.Calculate(dataSet); MACD *macd2=new MACD(SlotType); macd2.ListParam[1].Index = ListParam[1].Index; macd2.ListParam[2].Index = ListParam[2].Index; macd2.ListParam[3].Index = ListParam[3].Index; macd2.NumParam[0].Value = NumParam[1].Value; macd2.NumParam[1].Value = NumParam[3].Value; macd2.NumParam[2].Value = NumParam[5].Value; macd2.CheckParam[0].Checked=CheckParam[0].Checked; macd2.Calculate(dataSet); int previous= CheckParam[0].Checked ? 1 : 0; int firstBar=0; for(int c=0; c Data.High[bar - 1] && value < Data.Open[bar]) || // The Data.Open price jumps above the indicator (value1 < Data.Low[bar - 1] && value > Data.Open[bar]) || // The Data.Open price jumps below the indicator (Data.Close[bar-1]value && value > Data.Open[bar])) // The Data.Open price is in a negative gap tempVal=Data.Open[bar]; Component[1].Value[bar]=tempVal; // Entry or exit value } } else { ArrayResize(Component[1].Value, Data.Bars); ArrayInitialize(Component[1].Value,0); Component[1].FirstBar = firstBar; ArrayResize(Component[2].Value, Data.Bars); ArrayInitialize(Component[2].Value,0); Component[2].FirstBar = firstBar; } ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "Coral Value"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value,CoralBuffer); if(SlotType==SlotTypes_Open) { Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType_OpenPrice; } 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"; } if(SlotType==SlotTypes_Close) { Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType_ClosePrice; } 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 Moving Average rises") IndicatorRisesLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); else if(ListParam[0].Text=="The Moving Average falls") IndicatorFallsLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the Moving Average") BarOpensAboveIndicatorLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the Moving Average") BarOpensBelowIndicatorLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the Moving Average after opening below it") BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the Moving Average after opening above it") BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); else if(ListParam[0].Text=="The position opens above the 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 Moving Average") { Component[0].PosPriceDependence=PositionPriceDependence_BuyLowerSellHigher; 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 Moving Average") BarClosesBelowIndicatorLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); else if(ListParam[0].Text=="The bar closes above the Moving Average") BarClosesAboveIndicatorLogic(firstBar,previous,CoralBuffer,Component[1],Component[2]); } } //+------------------------------------------------------------------+ class CustomDonchianChannel : public Indicator { public: CustomDonchianChannel(SlotTypes slotType) { SlotType=slotType; IndicatorName="Custom Donchian Channel"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDeafultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CustomDonchianChannel::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); // Reading the parameters int iPeriod = (int)NumParam[0].Value; int iShift = (int)NumParam[1].Value; int iPrvs = CheckParam[0].Checked ? 1 : 0; // Calculation double adUpBand[]; ArrayResize(adUpBand, Data.Bars);ArrayInitialize(adUpBand,0); double adDnBand[]; ArrayResize(adDnBand, Data.Bars);ArrayInitialize(adDnBand,0); int iFirstBar=iPeriod+iShift+iPrvs+2; for(int iBar=iPeriod+iPrvs+2; iBar dMax) dMax = Data.High[iBar - i]; if(Data.Low[iBar - i] < dMin) dMin = Data.Low[iBar - i]; } adUpBand[iBar + iShift] = dMax; adDnBand[iBar + iShift] = dMin; } // Saving the components ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "Upper Band"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = iFirstBar; ArrayCopy(Component[0].Value,adUpBand); ArrayResize(Component[1].Value,Data.Bars); Component[1].CompName = "Lower Band"; Component[1].DataType = IndComponentType_IndicatorValue; Component[1].FirstBar = iFirstBar; ArrayCopy(Component[1].Value,adDnBand); ArrayResize(Component[2].Value,Data.Bars); Component[2].FirstBar=iFirstBar; ArrayResize(Component[3].Value,Data.Bars); Component[3].FirstBar=iFirstBar; // Sets the Component's type. if(SlotType==SlotTypes_Open) { Component[2].DataType = IndComponentType_OpenLongPrice; Component[2].CompName = "Long position entry price"; Component[3].DataType = IndComponentType_OpenShortPrice; Component[3].CompName = "Short position entry price"; } else if(SlotType==SlotTypes_OpenFilter) { Component[2].DataType = IndComponentType_AllowOpenLong; Component[2].CompName = "Is long entry allowed"; Component[3].DataType = IndComponentType_AllowOpenShort; Component[3].CompName = "Is short entry allowed"; } else if(SlotType==SlotTypes_Close) { Component[2].DataType = IndComponentType_CloseLongPrice; Component[2].CompName = "Long position closing price"; Component[3].DataType = IndComponentType_CloseShortPrice; Component[3].CompName = "Short position closing price"; } else if(SlotType==SlotTypes_CloseFilter) { Component[2].DataType = IndComponentType_ForceCloseLong; Component[2].CompName = "Close out long position"; Component[3].DataType = IndComponentType_ForceCloseShort; Component[3].CompName = "Close out short position"; } if(SlotType==SlotTypes_Open || SlotType==SlotTypes_Close) { if(iPeriod>1) { for(int iBar=iFirstBar; iBarData.High[iBar-1] && dValueUp dOpen) || // The Data.Open price jumps below the indicator (Data.Close[iBar - 1] < dValueUp && dValueUp < dOpen) || // The Data.Open price is in a positive gap (Data.Close[iBar - 1] > dValueUp && dValueUp > dOpen)) // The Data.Open price is in a negative gap dTempValUp=dOpen; // The entry/exit level is moved to Data.Open price // Lower band double dValueDown = adDnBand[iBar - iPrvs]; // Current value double dValueDown1 = adDnBand[iBar - iPrvs - 1]; // Previous value double dTempValDown = dValueDown; if((dValueDown1>Data.High[iBar-1] && dValueDown dOpen) || // The Data.Open price jumps below the indicator (Data.Close[iBar - 1] < dValueDown && dValueDown < dOpen) || // The Data.Open price is in a positive gap (Data.Close[iBar - 1] > dValueDown && dValueDown > dOpen)) // The Data.Open price is in a negative gap dTempValDown=dOpen; // The entry/exit level is moved to Data.Open price if(ListParam[0].Text=="Enter long at the Upper Band" || ListParam[0].Text=="Exit long at the Upper Band") { Component[2].Value[iBar] = dTempValUp; Component[3].Value[iBar] = dTempValDown; } else { Component[2].Value[iBar] = dTempValDown; Component[3].Value[iBar] = dTempValUp; } } } else { for(int iBar=2; iBar= adUpBand[iBar - iPrvs] ? 1 : 0; Component[3].Value[iBar] = Data.Low[iBar - 1] <= adDnBand[iBar - iPrvs] ? 1 : 0; } } else if(ListParam[0].Text=="The bar touches the Lower Band") { for(int iBar=iFirstBar+iPrvs; iBar= adUpBand[iBar - iPrvs] ? 1 : 0; } } } } //+------------------------------------------------------------------+ //## Import Start class IndicatorManager { public: Indicator *CreateIndicator(string indicatorName,SlotTypes slotType); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Indicator *IndicatorManager::CreateIndicator(string indicatorName,SlotTypes slotType) { if(indicatorName == "Moving Average") return new MovingAvrg(slotType); if(indicatorName == "Oscillator of MACD") return new OscillatorofMACD(slotType); if(indicatorName == "RSI MA Oscillator") return new RSIMAOscillator(slotType); if (indicatorName == "CoralTrend v1") return new CoralTrendv1(slotType); if (indicatorName == "Custom Donchian Channel") return new CustomDonchianChannel(slotType); return NULL; } //+------------------------------------------------------------------+ //## Import Start 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 21.03.2018 from Forex Strategy Builder Professional, v3.8"; strategy.RecommendedBars = 1000; strategy.FirstBar = 210; strategy.MinBarsRequired = 211; 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 = "CoralTrend v1"; 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("CoralTrend v1", 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 Moving Average"; 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.CheckParam[0].Enabled = true; strategy.Slot[0].IndicatorPointer.CheckParam[0].Caption = "Use previous bar value"; strategy.Slot[0].IndicatorPointer.CheckParam[0].Checked = true; strategy.Slot[1].IndicatorName = "Oscillator of MACD"; 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("Oscillator of MACD", 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 = "Oscillator of MACD changes its direction downward"; strategy.Slot[1].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[1].Caption = "Smoothing method"; strategy.Slot[1].IndicatorPointer.ListParam[1].Index = 2; strategy.Slot[1].IndicatorPointer.ListParam[1].Text = "Exponential"; strategy.Slot[1].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[2].Caption = "Base price"; strategy.Slot[1].IndicatorPointer.ListParam[2].Index = 0; strategy.Slot[1].IndicatorPointer.ListParam[2].Text = "Open"; strategy.Slot[1].IndicatorPointer.ListParam[3].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[3].Caption = "Signal line method"; strategy.Slot[1].IndicatorPointer.ListParam[3].Index = 2; strategy.Slot[1].IndicatorPointer.ListParam[3].Text = "Exponential"; strategy.Slot[1].IndicatorPointer.ListParam[4].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[4].Caption = "What to compare"; strategy.Slot[1].IndicatorPointer.ListParam[4].Index = 2; strategy.Slot[1].IndicatorPointer.ListParam[4].Text = "MACD lines"; strategy.Slot[1].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[0].Caption = "MACD1 slow MA"; strategy.Slot[1].IndicatorPointer.NumParam[0].Value = Slot1IndParam0; strategy.Slot[1].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[1].Caption = "MACD2 slow MA"; strategy.Slot[1].IndicatorPointer.NumParam[1].Value = Slot1IndParam1; strategy.Slot[1].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[2].Caption = "MACD1 fast MA"; strategy.Slot[1].IndicatorPointer.NumParam[2].Value = Slot1IndParam2; strategy.Slot[1].IndicatorPointer.NumParam[3].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[3].Caption = "MACD2 fast MA"; strategy.Slot[1].IndicatorPointer.NumParam[3].Value = Slot1IndParam3; strategy.Slot[1].IndicatorPointer.NumParam[4].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[4].Caption = "MACD1 Signal line"; strategy.Slot[1].IndicatorPointer.NumParam[4].Value = Slot1IndParam4; strategy.Slot[1].IndicatorPointer.NumParam[5].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[5].Caption = "MACD2 Signal line"; strategy.Slot[1].IndicatorPointer.NumParam[5].Value = Slot1IndParam5; strategy.Slot[1].IndicatorPointer.CheckParam[0].Enabled = true; strategy.Slot[1].IndicatorPointer.CheckParam[0].Caption = "Use previous bar value"; strategy.Slot[1].IndicatorPointer.CheckParam[0].Checked = false; strategy.Slot[2].IndicatorName = "Moving Average"; 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("Moving Average", 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 = 1; strategy.Slot[2].IndicatorPointer.ListParam[0].Text = "Moving Average falls"; 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 = 5; strategy.Slot[2].IndicatorPointer.ListParam[2].Text = "Typical"; strategy.Slot[2].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[0].Caption = "Period"; strategy.Slot[2].IndicatorPointer.NumParam[0].Value = Slot2IndParam0; strategy.Slot[2].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[1].Caption = "Shift"; strategy.Slot[2].IndicatorPointer.NumParam[1].Value = Slot2IndParam1; 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 = "RSI MA Oscillator"; 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("RSI MA Oscillator", 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 = 1; strategy.Slot[3].IndicatorPointer.ListParam[0].Text = "RSI MA Oscillator falls"; strategy.Slot[3].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[3].IndicatorPointer.ListParam[1].Caption = "Smoothing method"; strategy.Slot[3].IndicatorPointer.ListParam[1].Index = 1; strategy.Slot[3].IndicatorPointer.ListParam[1].Text = "Weighted"; strategy.Slot[3].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[3].IndicatorPointer.ListParam[2].Caption = "Signal line method"; strategy.Slot[3].IndicatorPointer.ListParam[2].Index = 0; strategy.Slot[3].IndicatorPointer.ListParam[2].Text = "Simple"; strategy.Slot[3].IndicatorPointer.ListParam[3].Enabled = true; strategy.Slot[3].IndicatorPointer.ListParam[3].Caption = "Base price"; strategy.Slot[3].IndicatorPointer.ListParam[3].Index = 5; strategy.Slot[3].IndicatorPointer.ListParam[3].Text = "Typical"; strategy.Slot[3].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.NumParam[0].Caption = "RSI period"; strategy.Slot[3].IndicatorPointer.NumParam[0].Value = Slot3IndParam0; strategy.Slot[3].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[3].IndicatorPointer.NumParam[1].Caption = "Signal line period"; strategy.Slot[3].IndicatorPointer.NumParam[1].Value = Slot3IndParam1; strategy.Slot[3].IndicatorPointer.CheckParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.CheckParam[0].Caption = "Use previous bar value"; strategy.Slot[3].IndicatorPointer.CheckParam[0].Checked = true; strategy.Slot[4].IndicatorName = "Custom Donchian Channel"; strategy.Slot[4].SlotType = SlotTypes_Close; strategy.Slot[4].SignalShift = 0; strategy.Slot[4].SignalRepeat = 0; strategy.Slot[4].IndicatorPeriod = DataPeriod_M1; strategy.Slot[4].IndicatorSymbol = ""; strategy.Slot[4].LogicalGroup = ""; strategy.Slot[4].IndicatorPointer = indicatorManager.CreateIndicator("Custom Donchian Channel", SlotTypes_Close); strategy.Slot[4].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[4].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[4].IndicatorPointer.ListParam[0].Text = "Exit long at the Upper Band"; strategy.Slot[4].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[1].Caption = "Base price"; strategy.Slot[4].IndicatorPointer.ListParam[1].Index = 0; strategy.Slot[4].IndicatorPointer.ListParam[1].Text = "High & Low"; strategy.Slot[4].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.NumParam[0].Caption = "Period"; strategy.Slot[4].IndicatorPointer.NumParam[0].Value = Slot4IndParam0; strategy.Slot[4].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[4].IndicatorPointer.NumParam[1].Caption = "Shift"; 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; delete indicatorManager; return strategy; } //+------------------------------------------------------------------+ //## Import Start #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)); } } //+------------------------------------------------------------------+ //## Import Start 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); } //+------------------------------------------------------------------+ //## Import Start 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; iindicatorValue+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; } } 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)); } //+------------------------------------------------------------------+ //## Import Start #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; // 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); // 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); // Specific MQ4 trading methods bool OpenNewPosition(int type,double lots,int stopLoss,int takeProfit); bool AddToCurrentPosition(int type,double lots,int stopLoss,int takeProfit); bool ReduceCurrentPosition(double lots,int stopLoss,int takeProfit); bool ReverseCurrentPosition(int type,double lots,int stopLoss,int takeProfit); bool CloseOrder(int orderTicket,double lots); bool SelectOrder(int orderTicket); bool SendOrder(int type,double lots,int stopLoss,int takeProfit); bool ModifyOrder(int orderTicket,double stopLossPrice,double takeProfitPrice); public: // Constructors ActionTrade(void); ~ActionTrade(void); // Properties double EntryAmount; double MaximumAmount; double AddingAmount; double ReducingAmount; string OrderComment; int MinDataBars; int ProtectionMinAccount; int ProtectionMaxStopLoss; int ExpertMagic; bool SeparateSLTP; bool WriteLogFile; bool FIFOorder; int TrailingStopMovingStep; int MaxLogLinesInFile; int BarCloseAdvance; // Methods int OnInit(void); void OnTick(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)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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, ExpertMagic)); 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("Expert Magic: "+IntegerToString(ExpertMagic)+", "+ "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) MarketInfo(_Symbol,MODE_STOPLEVEL)+pipsPoint; if(stopLevel<3*pipsPoint) stopLevel=3*pipsPoint; if(ProtectionMaxStopLoss>0 && ProtectionMaxStopLoss0 && AccountEquity()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, ExpertMagic)); } 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=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) MarketInfo(_Symbol, MODE_LOTSIZE); market.StopLevel = (int) MarketInfo(_Symbol, MODE_STOPLEVEL); market.Point = MarketInfo(_Symbol, MODE_POINT); market.TickValue = MarketInfo(_Symbol, MODE_TICKVALUE); market.MinLot = MarketInfo(_Symbol, MODE_MINLOT); market.MaxLot = MarketInfo(_Symbol, MODE_MAXLOT); market.LotStep = MarketInfo(_Symbol, MODE_LOTSTEP); market.MarginRequired = MarketInfo(_Symbol, MODE_MARGINREQUIRED); market.Spread = (market.Ask - market.Bid) / market.Point; if(market.MarginRequired=minDataBars) return (true); string message= "\n Cannot load enough bars! The expert needs minimum "+ IntegerToString(minDataBars)+" bars."+ "\n Please check the \"Use date\" option"+ " and set the \"From:\" and \"To:\" dates properly."; Comment(message); Print(message); return (false); } int bars=0; double rates[][6]; for(int attempt=0; attempt<10; attempt++) { RefreshRates(); bars=ArrayCopyRates(rates,_Symbol,_Period); if(bars=minDataBars); if(!isEnoughBars) { string message="There isn\'t enough bars. The expert needs minimum "+ IntegerToString(minDataBars)+" bars. "+ "Currently "+IntegerToString(bars)+" bars are loaded."+ "\n Press and hold the Home key to force MetaTrader loading more bars."; Comment(message); Print(message); } return (isEnoughBars); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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.PosComment = ""; int positions=0; for(int i=0; i=0 && pos.PosType!=OrderType()) { string message="There are open positions in different directions!"; Comment(message); Print(message); return (-1); } pos.PosType = OrderType(); pos.Direction = position.PosType == OP_FLAT ? PosDirection_None : position.PosType==OP_BUY ? PosDirection_Long : PosDirection_Short; pos.OpenTime = (OrderOpenTime() < pos.OpenTime) ? OrderOpenTime() : pos.OpenTime; pos.OpenPrice = (pos.Lots * pos.OpenPrice + OrderLots() * OrderOpenPrice()) / (pos.Lots + OrderLots()); pos.Lots += OrderLots(); pos.Commission += OrderCommission(); pos.Profit += OrderProfit() + pos.Commission; pos.StopLossPrice = OrderStopLoss(); pos.TakeProfitPrice = OrderTakeProfit(); pos.PosComment = OrderComment(); positions+=1; } if(pos.OpenPrice>0) pos.OpenPrice=NormalizeDouble(pos.OpenPrice,_Digits); if(pos.Lots==0) pos.OpenTime=D'2050.01.01 00:00'; return (positions); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ActionTrade::ManageOrderSend(int type,double lots,int stopLoss,int takeProfit, TrailingStopMode trlMode,int trlStop,int brkEven) { trailingMode = trlMode; trailingStop = trlStop; breakEven = brkEven; bool orderResponse=false; int positions=SetAggregatePosition(position); if(positions<0) return (false); if(positions==0) { // Open a new position. orderResponse=OpenNewPosition(type,lots,stopLoss,takeProfit); } else if(positions>0) { // There is an open position. if((position.PosType==OP_BUY && type==OP_BUY) || (position.PosType==OP_SELL && type==OP_SELL)) { orderResponse=AddToCurrentPosition(type,lots,stopLoss,takeProfit); } else if((position.PosType==OP_BUY && type==OP_SELL) || (position.PosType==OP_SELL && type==OP_BUY)) { if(MathAbs(position.Lots-lots)lots) orderResponse=ReduceCurrentPosition(lots,stopLoss,takeProfit); else if(position.Lots0) { if(SeparateSLTP) { if(WriteLogFile) logger.WriteLogLine("OpenNewPosition => SendOrder"); orderResponse=SendOrder(type,orderLots,0,0); if(orderResponse) { if(WriteLogFile) logger.WriteLogLine("OpenNewPosition => ModifyPosition"); double stopLossPrice=GetStopLossPrice(type,stopLoss); double takeProfitPrice=GetTakeProfitPrice(type,takeProfit); orderResponse=ModifyOrder(orderResponse,stopLossPrice,takeProfitPrice); } } else { orderResponse=SendOrder(type,orderLots,stopLoss,takeProfit); if(WriteLogFile) logger.WriteLogLine("OpenNewPosition: SendOrder Response = "+ (orderResponse ? "Ok" : "Failed")); if(!orderResponse && lastError==130) { // Invalid Stops. We'll check for forbidden direct set of SL and TP if(WriteLogFile) logger.WriteLogLine("OpenNewPosition: SendOrder"); orderResponse=SendOrder(type,lots,0,0); if(orderResponse) { if(WriteLogFile) logger.WriteLogLine("OpenNewPosition: ModifyPosition"); double stopLossPrice=GetStopLossPrice(type,stopLoss); double takeProfitPrice=GetTakeProfitPrice(type,takeProfit); orderResponse=ModifyOrder(orderResponse,stopLossPrice,takeProfitPrice); if(orderResponse) { SeparateSLTP=true; Print(AccountCompany()," marked with separate stops setting."); } } } } } SetAggregatePosition(position); if(WriteLogFile) logger.WriteLogLine(position.ToString()); return (orderResponse); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ActionTrade::CloseCurrentPosition() { bool orderResponse = false; int totalOrders = OrdersTotal(); int orders = 0; datetime openPos[][2]; for(int i=0; i=OrderLots()) ? OrderLots() : lots; CloseOrder(OrderTicket(),orderLots); lots-=orderLots; if(lots<=0) break; } double stopLossPrice=GetStopLossPrice(position.PosType,stopLoss); double takeProfitPrice=GetTakeProfitPrice(position.PosType,takeProfit); bool orderResponse=ModifyPosition(stopLossPrice,takeProfitPrice); SetAggregatePosition(position); consecutiveLosses=0; return (orderResponse); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ActionTrade::ReverseCurrentPosition(int type,double lots,int stopLoss,int takeProfit) { lots-=position.Lots; bool orderResponse=CloseCurrentPosition(); if(!orderResponse) return (false); orderResponse=OpenNewPosition(type,lots,stopLoss,takeProfit); SetAggregatePosition(position); consecutiveLosses=0; return (orderResponse); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ActionTrade::SendOrder(int type,double lots,int stopLoss,int takeProfit) { bool orderResponse = false; int response = -1; for(int attempt=0; attempt0) { stopLossPrice=CorrectStopLossPrice(OrderType(),stopLossPrice); takeProfitPrice=CorrectTakeProfitPrice(OrderType(),takeProfitPrice); } if(MathAbs(stopLossPrice-oldStopLoss)maxTPPrice) takeProfitPrice=maxTPPrice; } return (NormalizeEntryPrice(takeProfitPrice)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double ActionTrade::CorrectStopLossPrice(int type,double stopLossPrice) { if(stopLossPrice==epsilon) return (0); double bid = MarketInfo(_Symbol, MODE_BID); double ask = MarketInfo(_Symbol, MODE_ASK); if(type==OP_BUY) { double minSLPrice=bid-stopLevel*_Point; if(stopLossPrice>minSLPrice) stopLossPrice=minSLPrice; } else if(type==OP_SELL) { double maxSLPrice=ask+stopLevel*_Point; if(stopLossPrice= maxlot) size = maxlot; return (size); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::SetMaxStopLoss() { double bid = MarketInfo(_Symbol, MODE_BID); double ask = MarketInfo(_Symbol, MODE_ASK); double spread=(ask-bid)/_Point; for(int i=0; iProtectionMaxStopLoss+spread) { stopLossPrice=(type==OP_BUY) ? posOpenPrice-_Point *(ProtectionMaxStopLoss+spread) : posOpenPrice+_Point *(ProtectionMaxStopLoss+spread); stopLossPrice=CorrectStopLossPrice(type,stopLossPrice); if(WriteLogFile) logger.WriteLogRequest("SetMaxStopLoss","StopLoss="+ DoubleToString(stopLossPrice,_Digits)); bool isSuccess=ModifyOrder(orderTicket,stopLossPrice,takeProfitPrice); if(isSuccess) Print("MaxStopLoss(",ProtectionMaxStopLoss,") set StopLoss to ", DoubleToString(stopLossPrice,_Digits)); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::SetBreakEvenStop() { if(SetAggregatePosition(position)<=0) return; double breakeven=stopLevel; if(breakeven=_Point*breakeven) { if(position.StopLossPricestopLossPrice+pipsValue) { if(stopLossPrice>ask) { if(stopLossPrice=position.OpenPrice+_Point*trailingStop) { if(position.StopLossPrice30*1000) { Print("The waiting limit exceeded!"); return (false); } if(IsTradeAllowed()) { RefreshRates(); return (true); } Sleep(100); } return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ActionTrade::ActivateProtectionMinAccount() { CloseCurrentPosition(); string account = DoubleToString(AccountEquity(), 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); } //+------------------------------------------------------------------+ 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.ExpertMagic = Expert_Magic; actionTrade.SeparateSLTP = Separate_SL_TP; actionTrade.WriteLogFile = Write_Log_File; actionTrade.TrailingStopMovingStep = TrailingStop_Moving_Step; actionTrade.FIFOorder = FIFO_order; 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 OnDeinit(const int reason) { actionTrade.OnDeinit(reason); if(CheckPointer(actionTrade)==POINTER_DYNAMIC) delete actionTrade; }