//+--------------------------------------------------------------------+ //| 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 "46.0" #property strict // ----------------------- External variables ----------------------- // static input string StrategyProperties__ = "------------"; // ------ Strategy Properties ------ static input double Entry_Amount = 0.6; // Amount for a new position [lot] static input double Maximum_Amount = 0.6; // Maximum position amount [lot] static input double Adding_Amount = 0.6; // Amount to add on addition [lot] static input double Reducing_Amount = 0.6; // Amount to close on reduction [lot] input int Stop_Loss = 2000; // Stop Loss [point] input int Take_Profit = 100; // Take Profit [point] input int Break_Even = 1000; // Break Even [point] static input double Martingale_Multiplier = 0; // Martingale Multiplier static input string IndicatorName0 = "Previous High Low"; // ------ Indicator parameters ------ input int Slot0IndParam0 = -3; // Vertical shift static input string IndicatorName1 = "Overbought Oversold Index"; // ------ Indicator parameters ------ input int Slot1IndParam0 = 52; // Period input int Slot1IndParam1 = 95; // Level static input string IndicatorName2 = "Vidya Moving Average"; // ------ Indicator parameters ------ input int Slot2IndParam0 = 8; // Period input int Slot2IndParam1 = 60; // Smooth static input string IndicatorName5 = "Entry Time"; // ------ Indicator parameters ------ input int Slot5IndParam0 = 0; // From hour (incl.) input int Slot5IndParam1 = 0; // From min (incl.) input int Slot5IndParam2 = 24; // Until hour (excl.) input int Slot5IndParam3 = 0; // Until min (excl.) static input string IndicatorName7 = "Hourly High Low"; // ------ Indicator parameters ------ input int Slot7IndParam0 = 0; // Start hour (incl.) input int Slot7IndParam1 = 0; // Start minutes (incl.) input int Slot7IndParam2 = 24; // End hour (excl.) input int Slot7IndParam3 = 0; // End minutes (excl.) input int Slot7IndParam4 = 0; // Vertical shift static input string IndicatorName8 = "Take Profit"; // ------ Indicator parameters ------ input int Slot8IndParam0 = 181; // Take Profit static input string ExpertSettings__ = "------------"; // ------ Expert Settings ------ // A unique number of the expert's orders. static input int Expert_Magic = 12101023; // 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; enum DataPeriod { DataPeriod_M1 = 1, DataPeriod_M5 = 5, DataPeriod_M15 = 15, DataPeriod_M30 = 30, DataPeriod_H1 = 60, DataPeriod_H4 = 240, DataPeriod_D1 = 1440, DataPeriod_W1 = 10080, DataPeriod_MN1 = 43200 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum PosDirection { PosDirection_None, PosDirection_Long, PosDirection_Short, PosDirection_Closed }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OrderDirection { OrderDirection_None, OrderDirection_Buy, OrderDirection_Sell }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum StrategyPriceType { StrategyPriceType_Open, StrategyPriceType_Close, StrategyPriceType_Indicator, StrategyPriceType_CloseAndReverse, StrategyPriceType_Unknown }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum ExecutionTime { ExecutionTime_DuringTheBar, ExecutionTime_AtBarOpening, ExecutionTime_AtBarClosing, ExecutionTime_CloseAndReverse }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TraderOrderType { TraderOrderType_Buy = 0, TraderOrderType_Sell = 1, TraderOrderType_BuyLimit = 2, TraderOrderType_SellLimit = 3, TraderOrderType_BuyStop = 4, TraderOrderType_SellStop = 5 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TradeDirection { TradeDirection_None, TradeDirection_Long, TradeDirection_Short, TradeDirection_Both }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum LongTradeEntryPrice { LongTradeEntryPrice_Bid, LongTradeEntryPrice_Ask, LongTradeEntryPrice_Chart }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OperationType { OperationType_Buy, OperationType_Sell, OperationType_Close, OperationType_Modify }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TickType { TickType_Open = 0, TickType_OpenClose = 1, TickType_Regular = 2, TickType_Close = 3, TickType_AfterClose = 4 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum InstrumentType { InstrumentType_Forex, InstrumentType_CFD, InstrumentType_Index }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum SlotTypes { SlotTypes_NotDefined = 0, SlotTypes_Open = 1, SlotTypes_OpenFilter = 2, SlotTypes_Close = 4, SlotTypes_CloseFilter = 8 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum IndComponentType { IndComponentType_NotDefined, IndComponentType_OpenLongPrice, IndComponentType_OpenShortPrice, IndComponentType_OpenPrice, IndComponentType_CloseLongPrice, IndComponentType_CloseShortPrice, IndComponentType_ClosePrice, IndComponentType_OpenClosePrice, IndComponentType_IndicatorValue, IndComponentType_AllowOpenLong, IndComponentType_AllowOpenShort, IndComponentType_ForceCloseLong, IndComponentType_ForceCloseShort, IndComponentType_ForceClose, IndComponentType_Other }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum PositionPriceDependence { PositionPriceDependence_None, PositionPriceDependence_PriceBuyHigher, PositionPriceDependence_PriceBuyLower, PositionPriceDependence_PriceSellHigher, PositionPriceDependence_PriceSellLower, PositionPriceDependence_BuyHigherSellLower, PositionPriceDependence_BuyLowerSelHigher,// Deprecated PositionPriceDependence_BuyLowerSellHigher }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum BasePrice { BasePrice_Open = 0, BasePrice_High = 1, BasePrice_Low = 2, BasePrice_Close = 3, BasePrice_Median = 4, // Price[bar] = (Low[bar] + High[bar]) / 2; BasePrice_Typical = 5, // Price[bar] = (Low[bar] + High[bar] + Close[bar]) / 3; BasePrice_Weighted = 6 // Price[bar] = (Low[bar] + High[bar] + 2 * Close[bar]) / 4; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum MAMethod { MAMethod_Simple = 0, MAMethod_Weighted = 1, MAMethod_Exponential = 2, MAMethod_Smoothed = 3 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum SameDirSignalAction { SameDirSignalAction_Nothing, SameDirSignalAction_Add, SameDirSignalAction_Winner, SameDirSignalAction_Loser, }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum OppositeDirSignalAction { OppositeDirSignalAction_Nothing, OppositeDirSignalAction_Reduce, OppositeDirSignalAction_Close, OppositeDirSignalAction_Reverse }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum PermanentProtectionType { PermanentProtectionType_Relative, PermanentProtectionType_Absolute }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum TrailingStopMode { TrailingStopMode_Bar, TrailingStopMode_Tick }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum IndicatorLogic { IndicatorLogic_The_indicator_rises, IndicatorLogic_The_indicator_falls, IndicatorLogic_The_indicator_is_higher_than_the_level_line, IndicatorLogic_The_indicator_is_lower_than_the_level_line, IndicatorLogic_The_indicator_crosses_the_level_line_upward, IndicatorLogic_The_indicator_crosses_the_level_line_downward, IndicatorLogic_The_indicator_changes_its_direction_upward, IndicatorLogic_The_indicator_changes_its_direction_downward, IndicatorLogic_The_price_buy_is_higher_than_the_ind_value, IndicatorLogic_The_price_buy_is_lower_than_the_ind_value, IndicatorLogic_The_price_open_is_higher_than_the_ind_value, IndicatorLogic_The_price_open_is_lower_than_the_ind_value, IndicatorLogic_It_does_not_act_as_a_filter, }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum BandIndLogic { BandIndLogic_The_bar_opens_below_the_Upper_Band, BandIndLogic_The_bar_opens_above_the_Upper_Band, BandIndLogic_The_bar_opens_below_the_Lower_Band, BandIndLogic_The_bar_opens_above_the_Lower_Band, BandIndLogic_The_position_opens_below_the_Upper_Band, BandIndLogic_The_position_opens_above_the_Upper_Band, BandIndLogic_The_position_opens_below_the_Lower_Band, BandIndLogic_The_position_opens_above_the_Lower_Band, BandIndLogic_The_bar_opens_below_Upper_Band_after_above, BandIndLogic_The_bar_opens_above_Upper_Band_after_below, BandIndLogic_The_bar_opens_below_Lower_Band_after_above, BandIndLogic_The_bar_opens_above_Lower_Band_after_below, BandIndLogic_The_bar_closes_below_the_Upper_Band, BandIndLogic_The_bar_closes_above_the_Upper_Band, BandIndLogic_The_bar_closes_below_the_Lower_Band, BandIndLogic_The_bar_closes_above_the_Lower_Band, BandIndLogic_It_does_not_act_as_a_filter }; //+------------------------------------------------------------------+ bool LabelCreate(const long chart_ID = 0, // chart's ID const string name = "Label", // label name const int sub_window = 0, // subwindow index const int x = 0, // X coordinate const int y = 0, // Y coordinate const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER,// chart corner for anchoring const string text = "Label", // text const string font = "Arial", // font const int font_size = 8, // font size const color clr = clrWhite, // color const double angle = 0.0, // text slope const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER,// anchor type const bool back = false, // in the background const bool selection = false, // highlight to move const bool hidden = true, // hidden in the object list const string tooltip = "\n", // sets the tooltip const long z_order = 0) // priority for mouse click { ResetLastError(); if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)) { Print(__FUNCTION__,": failed to create text label! Error code = ",GetLastError()); return (false); } ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); ObjectSetString(chart_ID,name,OBJPROP_TEXT,text); ObjectSetString(chart_ID,name,OBJPROP_FONT,font); ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size); ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle); ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor); ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); ObjectSetString(chart_ID,name,OBJPROP_TOOLTIP,tooltip); ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool LabelTextChange(const long chart_ID,const string name,const string text) { ResetLastError(); if(!ObjectSetString(chart_ID,name,OBJPROP_TEXT,text)) { Print(__FUNCTION__,": failed to change the text! Error code = ",GetLastError()); return (false); } return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool LabelDelete(const long chart_ID=0,const string name="Label") { if(!ObjectDelete(chart_ID,name)) { Print(__FUNCTION__,": failed to delete a text label! Error code = ",GetLastError()); return (false); } return (true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ color GetChartForeColor(const long chartId=0) { long foreColor=clrWhite; ChartGetInteger(chartId,CHART_COLOR_FOREGROUND,0,foreColor); return ((color) foreColor); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ color GetChartBackColor(const long chartId=0) { long backColor=clrBlack; ChartGetInteger(chartId,CHART_COLOR_BACKGROUND,0,backColor); return ((color) backColor); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string LoadStringFromFile(string filename) { string text; int intSize; int handle= FileOpen(filename,FILE_TXT|FILE_READ|FILE_ANSI); if(handle == INVALID_HANDLE) return ""; while(!FileIsEnding(handle)) { intSize=FileReadInteger(handle,INT_VALUE); text+=FileReadString(handle,intSize); } FileClose(handle); return text; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void SaveStringToFile(string filename,string text) { int handle= FileOpen(filename,FILE_TXT|FILE_WRITE|FILE_ANSI); if(handle == INVALID_HANDLE) return; FileWriteString(handle,text); FileClose(handle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool ArrayContainsString(const string &array[],string text) { for(int i=0; iindexFromEnd) ? Value[bars-indexFromEnd-1]: 0; return (lastValue); } //+------------------------------------------------------------------+ class ListParameter { public: // Constructors ListParameter() { Caption = ""; Text = ""; Index = -1; Enabled = false; } // Properties string Caption; string Text; int Index; bool Enabled; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class NumericParameter { public: // Constructor NumericParameter() { Caption = ""; Value = 0; Enabled = false; } // Properties string Caption; double Value; bool Enabled; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CheckParameter { public: // Constructor CheckParameter() { Caption = ""; Checked = false; Enabled = false; } // Properties string Caption; bool Checked; bool Enabled; }; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Indicator { protected: double Sigma(void); double Epsilon(void); void NormalizeComponentValue(const double &componentValue[],const datetime &strategyTime[], int ltfShift,bool isCloseFilterShift,double &output[]); int NormalizeComponentFirstBar(int componentFirstBar,datetime &strategyTime[]); bool IsSignalComponent(IndComponentType componentType); void Price(BasePrice priceType,double &price[]); void MovingAverage(int period,int shift,MAMethod maMethod,const double &source[],double &movingAverage[]); void OscillatorLogic(int firstBar,int previous,const double &adIndValue[],double levelLong,double levelShort, IndicatorComp &indCompLong,IndicatorComp &indCompShort,IndicatorLogic indLogic); void NoDirectionOscillatorLogic(int firstBar,int previous,const double &adIndValue[],double dLevel, IndicatorComp &indComp,IndicatorLogic indLogic); void BandIndicatorLogic(int firstBar,int previous,const double &adUpperBand[],const double &adLowerBand[], IndicatorComp &indCompLong,IndicatorComp &indCompShort,BandIndLogic indLogic); void IndicatorRisesLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorFallsLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorChangesItsDirectionUpward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void IndicatorChangesItsDirectionDownward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void IndicatorIsHigherThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorIsLowerThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorCrossesAnotherIndicatorUpwardLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void IndicatorCrossesAnotherIndicatorDownwardLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void BarOpensAboveIndicatorLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void BarOpensBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort); void BarOpensAboveIndicatorAfterOpeningBelowLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void BarOpensBelowIndicatorAfterOpeningAboveLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void BarClosesAboveIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); void BarClosesBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort); public: // Constructors Indicator(void); ~Indicator(void); // Properties string IndicatorName; string WarningMessage; bool IsDiscreteValues; bool UsePreviousBarValue; // Important! Otdated Do not use. bool IsSeparateChart; bool IsBacktester; bool IsDeafultGroupAll; // Important! Outdated. Do not use. bool IsDefaultGroupAll; bool IsAllowLTF; SlotTypes SlotType; ExecutionTime ExecTime; ListParameter *ListParam[5]; NumericParameter *NumParam[6]; CheckParameter *CheckParam[2]; IndicatorComp *Component[10]; DataSet *Data; // Methods virtual void Calculate(DataSet &dataSet); void NormalizeComponents(DataSet &strategyDataSet,int ltfShift,bool isCloseFilterShift); void ShiftSignal(int shift); void RepeatSignal(int repeat); int Components(void); string IndicatorParamToString(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Indicator::Indicator(void) { IndicatorName=""; IsBacktester = false; IsDiscreteValues = false; IsSeparateChart = false; IsDeafultGroupAll = false; IsDefaultGroupAll = false; IsAllowLTF = true; SlotType = SlotTypes_NotDefined; ExecTime = ExecutionTime_DuringTheBar; for(int i=0; i<5; i++) ListParam[i]=new ListParameter(); for(int i=0; i<6; i++) NumParam[i]=new NumericParameter(); for(int i=0; i<2; i++) CheckParam[i]=new CheckParameter(); for(int i=0; i<10; i++) Component[i]=new IndicatorComp(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Indicator::~Indicator(void) { for(int i=0; i<5; i++) delete ListParam[i]; for(int i=0; i<6; i++) delete NumParam[i]; for(int i=0; i<2; i++) delete CheckParam[i]; for(int i=0; i<10; i++) delete Component[i]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::Calculate(DataSet &dataSet) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::NormalizeComponents(DataSet &strategyDataSet,int ltfShift,bool isCloseFilterShift) { for(int i=0; i=ltfOpenTime && time=ltfCloseTime) break; } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int Indicator::NormalizeComponentFirstBar(int componentFirstBar,datetime &strategyTime[]) { datetime firstBarTime=Data.Time[componentFirstBar]; for(int bar=0; bar=firstBarTime) return bar; return componentFirstBar; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Indicator::IsSignalComponent(IndComponentType componentType) { return componentType == IndComponentType_AllowOpenLong || componentType == IndComponentType_AllowOpenShort || componentType == IndComponentType_CloseLongPrice || componentType == IndComponentType_ClosePrice || componentType == IndComponentType_CloseShortPrice || componentType == IndComponentType_ForceClose || componentType == IndComponentType_ForceCloseLong || componentType == IndComponentType_ForceCloseShort || componentType == IndComponentType_OpenClosePrice || componentType == IndComponentType_OpenLongPrice || componentType == IndComponentType_OpenPrice || componentType == IndComponentType_OpenShortPrice; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int Indicator::Components(void) { for(int i=0; i<10; i++) if(Component[i].DataType==IndComponentType_NotDefined) return (i); return (10); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Indicator::IndicatorParamToString(void) { string text; for(int i=0; i<5; i++) if(ListParam[i].Enabled) text+=StringFormat("%s: %s\n",ListParam[i].Caption,ListParam[i].Text); for(int i=0; i<6; i++) if(NumParam[i].Enabled) text+=StringFormat("%s: %g\n",NumParam[i].Caption,NumParam[i].Value); for(int i=0; i<2; i++) if(CheckParam[i].Enabled) text+=StringFormat("%s: %s\n",CheckParam[i].Caption,(CheckParam[i].Checked ? "Yes" : "No")); return (text); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::Price(BasePrice priceType,double &price[]) { ArrayResize(price,Data.Bars); ArrayInitialize(price,0); switch(priceType) { case BasePrice_Open: ArrayCopy(price,Data.Open); break; case BasePrice_High: ArrayCopy(price,Data.High); break; case BasePrice_Low: ArrayCopy(price,Data.Low); break; case BasePrice_Close: ArrayCopy(price,Data.Close); break; case BasePrice_Median: for(int bar=0; barbars || period+shift<=0 || period+shift>bars) { // Error in the parameters string message=IndicatorName+" "+Data.Symbol+" "+DataPeriodToString(Data.Period)+ "Wrong MovingAverage parameters(Period: "+IntegerToString(period)+ ", Shift: "+IntegerToString(shift)+ ", Source bars: "+IntegerToString(bars)+")"; Print(message); ArrayCopy(movingAverage,source); return; } for(int bar=0; baradIndValue[baseBar]; if(!IsDiscreteValues) // Aroon oscillator uses IsDiscreteValues = true { bool isNoChange=true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } } indCompLong.Value[bar] = adIndValue[baseBar] < adIndValue[currentBar] - sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[baseBar] > adIndValue[currentBar] + sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_falls: for(int bar=firstBar; bar adIndValue[baseBar]; if(!IsDiscreteValues) // Aroon oscillator uses IsDiscreteValues = true { bool isNoChange=true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } } indCompLong.Value[bar] = adIndValue[baseBar] > adIndValue[currentBar] + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[baseBar] < adIndValue[currentBar] - sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_is_higher_than_the_level_line: for(int bar=firstBar; bar levelLong + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[bar - previous] < levelShort - sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_is_lower_than_the_level_line: for(int bar=firstBar; bar levelShort + sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_crosses_the_level_line_upward: for(int bar=firstBar; barfirstBar) baseBar--; indCompLong.Value[bar]=(adIndValue[baseBar]levelLong+sigma) ? 1 : 0; indCompShort.Value[bar]=(adIndValue[baseBar]>levelShort+sigma && adIndValue[bar-previous]firstBar) baseBar--; indCompLong.Value[bar]=(adIndValue[baseBar]>levelLong+sigma && adIndValue[bar-previous]levelShort+sigma) ? 1 : 0; } break; case IndicatorLogic_The_indicator_changes_its_direction_upward: for(int bar=firstBar; barfirstBar) bar1--; int iBar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[iBar2])firstBar) iBar2--; indCompLong.Value[bar]=(adIndValue[iBar2]>adIndValue[bar1] && adIndValue[bar1]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; } break; case IndicatorLogic_The_indicator_changes_its_direction_downward: for(int bar=firstBar; barfirstBar) bar1--; int iBar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[iBar2])firstBar) iBar2--; indCompLong.Value[bar]=(adIndValue[iBar2]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; indCompShort.Value[bar]=(adIndValue[iBar2]>adIndValue[bar1] && adIndValue[bar1] adIndValue[baseBar]; bool isNoChange = true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } indComp.Value[bar]=adIndValue[baseBar] adIndValue[baseBar]; bool isNoChange = true; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } indComp.Value[bar]=adIndValue[baseBar]>adIndValue[currentBar]+sigma ? 1 : 0; } break; case IndicatorLogic_The_indicator_is_higher_than_the_level_line: for(int bar=firstBar; bardLevel+sigma ? 1 : 0; break; case IndicatorLogic_The_indicator_is_lower_than_the_level_line: for(int bar=firstBar; barfirstBar) baseBar--; indComp.Value[bar]=(adIndValue[baseBar]dLevel+sigma) ? 1 : 0; } break; case IndicatorLogic_The_indicator_crosses_the_level_line_downward: for(int bar=firstBar; barfirstBar) baseBar--; indComp.Value[bar]=(adIndValue[baseBar]>dLevel+sigma && adIndValue[bar-previous]firstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indComp.Value[bar]=(adIndValue[bar2]>adIndValue[bar1] && adIndValue[bar1]firstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indComp.Value[bar]=(adIndValue[bar2]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; } break; default: return; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BandIndicatorLogic(int firstBar,int previous,const double &adUpperBand[],const double &adLowerBand[], IndicatorComp &indCompLong,IndicatorComp &indCompShort,BandIndLogic indLogic) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adLowerBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_above_the_Upper_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Open[bar] < adLowerBand[bar - previous] - sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_below_the_Lower_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_above_the_Lower_Band: for(int bar=firstBar; bar adLowerBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Open[bar] < adUpperBand[bar - previous] - sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_below_Upper_Band_after_above: for(int bar=firstBar; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]adUpperBand[baseBar-previous]+sigma ? 1 : 0; baseBar=bar-1; while(MathAbs(Data.Open[baseBar]-adLowerBand[baseBar-previous])firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]>adLowerBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]>adUpperBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]adLowerBand[baseBar-previous]+sigma ? 1 : 0; } break; case BandIndLogic_The_bar_opens_below_Lower_Band_after_above: for(int bar=firstBar; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]adLowerBand[baseBar-previous]+sigma ? 1 : 0; baseBar=bar-1; while(MathAbs(Data.Open[baseBar]-adUpperBand[baseBar-previous])firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]>adUpperBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]>adLowerBand[bar-previous]+sigma && Data.Open[baseBar]firstBar) baseBar--; indCompShort.Value[bar]=Data.Open[bar]adUpperBand[baseBar-previous]+sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_below_the_Upper_Band: for(int bar=firstBar; bar adLowerBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_above_the_Upper_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Close[bar] < adLowerBand[bar - previous] - sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_below_the_Lower_Band: for(int bar=firstBar; bar adUpperBand[bar - previous] + sigma ? 1 : 0; } break; case BandIndLogic_The_bar_closes_above_the_Lower_Band: for(int bar=firstBar; bar adLowerBand[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Close[bar] < adUpperBand[bar - previous] - sigma ? 1 : 0; } break; default: return; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorRisesLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adIndValue[baseBar]; while(MathAbs(adIndValue[currentBar]-adIndValue[baseBar])firstBar) { isNoChange=(isHigher==(adIndValue[baseBar+1]>adIndValue[baseBar])); baseBar--; } indCompLong.Value[bar] = adIndValue[currentBar] > adIndValue[baseBar] + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[currentBar] < adIndValue[baseBar] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorFallsLogic(int firstBar,int previous,const double &adIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) { isNoChange=(isLower==(adIndValue[baseBar+1] adIndValue[baseBar] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorIsHigherThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adAnotherIndValue[currentBar] + sigma ? 1 : 0; indCompShort.Value[bar] = adIndValue[currentBar] < adAnotherIndValue[currentBar] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorIsLowerThanAnotherIndicatorLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adAnotherIndValue[currentBar] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorChangesItsDirectionUpward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma= Sigma(); for(int bar = firstBar; barfirstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indCompLong.Value[bar]=(adIndValue[bar2]>adIndValue[bar1] && adIndValue[bar1]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorChangesItsDirectionDownward(int firstBar,int previous,double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma= Sigma(); for(int bar = firstBar; barfirstBar) bar1--; int bar2=bar1-1>firstBar ? bar1-1 : firstBar; while(MathAbs(adIndValue[bar1]-adIndValue[bar2])firstBar) bar2--; indCompLong.Value[bar]=(adIndValue[bar2]adIndValue[bar0] && bar1==bar0-1) ? 1 : 0; indCompShort.Value[bar]=(adIndValue[bar2]>adIndValue[bar1] && adIndValue[bar1]firstBar) baseBar--; indCompLong.Value[bar]=adIndValue[currentBar]>adAnotherIndValue[currentBar]+sigma && adIndValue[baseBar]adAnotherIndValue[baseBar]+sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::IndicatorCrossesAnotherIndicatorDownwardLogic(int firstBar,int previous,const double &adIndValue[], double &adAnotherIndValue[],IndicatorComp &indCompLong, IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) { baseBar--; } indCompLong.Value[bar]=adIndValue[currentBar]adAnotherIndValue[baseBar]+sigma ? 1 : 0; indCompShort.Value[bar]=adIndValue[currentBar]>adAnotherIndValue[currentBar]+sigma && adIndValue[baseBar] adIndValue[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Open[bar] < adIndValue[bar - previous] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarOpensBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adIndValue[bar - previous] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarOpensAboveIndicatorAfterOpeningBelowLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]>adIndValue[bar-previous]+sigma && Data.Open[baseBar]adIndValue[baseBar-previous]+sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarOpensBelowIndicatorAfterOpeningAboveLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; barfirstBar) baseBar--; indCompLong.Value[bar]=Data.Open[bar]adIndValue[baseBar-previous]+sigma ? 1 : 0; indCompShort.Value[bar]=Data.Open[bar]>adIndValue[bar-previous]+sigma && Data.Open[baseBar] adIndValue[bar - previous] + sigma ? 1 : 0; indCompShort.Value[bar] = Data.Close[bar] < adIndValue[bar - previous] - sigma ? 1 : 0; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Indicator::BarClosesBelowIndicatorLogic(int firstBar,int previous,const double &adIndValue[], IndicatorComp &indCompLong,IndicatorComp &indCompShort) { double sigma=Sigma(); firstBar=MathMax(firstBar,2); for(int bar=0; bar adIndValue[bar - previous] + sigma ? 1 : 0; } } //+------------------------------------------------------------------+ class DaysOfWeek : public Indicator { public: DaysOfWeek(SlotTypes slotType); virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void DaysOfWeek::DaysOfWeek(SlotTypes slotType) { SlotType = slotType; IndicatorName = "Day of Week"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void DaysOfWeek::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); int dowFromDay = ListParam[1].Index; int dowUntilDay = ListParam[2].Index; const int firstBar=1; double signal[]; ArrayResize(signal,Data.Bars); ArrayInitialize(signal,0); for(int bar=firstBar; bar=dowFromDay && timedowUntilDay) signal[bar]=(time>=dowFromDay || time=fromTime && barTimeuntilTime) adBars[bar]=barTime>=fromTime || barTime=fromTime && barTimetoTime) isOnTime=barTime>=fromTime || barTime Data.Low[bar]) dMinPrice = Data.Low[bar]; } if(!isOnTime && isOnTimePrev) { adHighPrice[bar]= dMaxPrice; adLowPrice[bar] = dMinPrice; dMaxPrice = DBL_MIN; dMinPrice = DBL_MAX; } else { adHighPrice[bar] = adHighPrice[bar - 1]; adLowPrice[bar] = adLowPrice[bar - 1]; } isOnTimePrev=isOnTime; } double adUpperBand[]; ArrayResize(adUpperBand,Data.Bars); ArrayInitialize(adUpperBand,0); double adLowerBand[]; ArrayResize(adLowerBand,Data.Bars); ArrayInitialize(adLowerBand,0); for(int bar=firstBar; bar max) max = Data.High[bar - i]; if(Data.Low[bar - i] < min) min = Data.Low[bar - i]; } if (MathAbs(min - max) < 0.00001) obos[bar] = 0; else obos[bar] = 100*(Data.Close[bar] - min)/(max - min); } // Saving the components ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "OBOS"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value,obos); 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=="Overbought Oversold Index rises") indLogic=IndicatorLogic_The_indicator_rises; else if(ListParam[0].Text=="Overbought Oversold Index falls") indLogic=IndicatorLogic_The_indicator_falls; else if(ListParam[0].Text=="Overbought Oversold Index is higher than the Level line") indLogic=IndicatorLogic_The_indicator_is_higher_than_the_level_line; else if(ListParam[0].Text=="Overbought Oversold Index is lower than the Level line") indLogic=IndicatorLogic_The_indicator_is_lower_than_the_level_line; else if(ListParam[0].Text=="Overbought Oversold Index crosses the Level line upward") indLogic=IndicatorLogic_The_indicator_crosses_the_level_line_upward; else if(ListParam[0].Text=="Overbought Oversold Index crosses the Level line downward") indLogic=IndicatorLogic_The_indicator_crosses_the_level_line_downward; else if(ListParam[0].Text=="Overbought Oversold Index changes its direction upward") indLogic=IndicatorLogic_The_indicator_changes_its_direction_upward; else if(ListParam[0].Text=="Overbought Oversold Index changes its direction downward") indLogic=IndicatorLogic_The_indicator_changes_its_direction_downward; OscillatorLogic(firstBar,previous,obos,level,100-level,Component[1],Component[2],indLogic); } //+------------------------------------------------------------------+ class PreviousHighLow : public Indicator { public: PreviousHighLow(SlotTypes slotType) { SlotType=slotType; IndicatorName="Previous High Low"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void PreviousHighLow::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); double verticalShift=NumParam[0].Value*Data.Point; int previous = CheckParam[0].Checked ? 1 : 0; int firstBar = previous+2; // Calculation double high[]; ArrayResize(high,Data.Bars); ArrayInitialize(high,0); double low[]; ArrayResize(low,Data.Bars); ArrayInitialize(low,0); double upperBand[]; ArrayResize(upperBand,Data.Bars); ArrayInitialize(upperBand,0); double lowerBand[]; ArrayResize(lowerBand,Data.Bars); ArrayInitialize(lowerBand,0); for(int bar=firstBar; baradBasePrice[bar-1]) adCMO1[bar]=adBasePrice[bar]-adBasePrice[bar-1]; if(adBasePrice[bar]Data.High[bar-1] && dValueData.Open[bar]) || // It jumps above the current bar (Data.Close[bar - 1] < dValue && dValue < Data.Open[bar]) || // Positive gap (Data.Close[bar - 1] > dValue && dValue > Data.Open[bar])) // Negative gap dTempVal=Data.Open[bar]; Component[1].Value[bar]=dTempVal; } } else { ArrayResize(Component[1].Value,Data.Bars); Component[1].FirstBar=firstBar; ArrayResize(Component[2].Value,Data.Bars); Component[2].FirstBar=firstBar; } ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "MA Value"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value,adMA); if(SlotType==SlotTypes_Open) { Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType_OpenPrice; } else if(SlotType==SlotTypes_OpenFilter) { Component[1].DataType = IndComponentType_AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType_AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if(SlotType==SlotTypes_Close) { Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType_ClosePrice; } else if(SlotType==SlotTypes_CloseFilter) { Component[1].DataType = IndComponentType_ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType_ForceCloseShort; Component[2].CompName = "Close out short position"; } if(SlotType==SlotTypes_OpenFilter || SlotType==SlotTypes_CloseFilter) { if(ListParam[0].Text=="The Vidya Moving Average rises") IndicatorRisesLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The Vidya Moving Average falls") IndicatorFallsLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the Vidya Moving Average") BarOpensAboveIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the Vidya Moving Average") BarOpensBelowIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the Vidya Moving Average after opening below it") BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the Vidya Moving Average after opening above it") BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The position opens above the Vidya Moving Average") { Component[0].PosPriceDependence=PositionPriceDependence_BuyHigherSellLower; Component[0].UsePreviousBar=previous; Component[1].DataType=IndComponentType_Other; Component[1].ShowInDynInfo=false; Component[2].DataType=IndComponentType_Other; Component[2].ShowInDynInfo=false; } else if(ListParam[0].Text=="The position opens below the Vidya Moving Average") { Component[0].PosPriceDependence=PositionPriceDependence_BuyLowerSelHigher; Component[0].UsePreviousBar=previous; Component[1].DataType=IndComponentType_Other; Component[1].ShowInDynInfo=false; Component[2].DataType=IndComponentType_Other; Component[2].ShowInDynInfo=false; } else if(ListParam[0].Text=="The bar closes below the Vidya Moving Average") BarClosesBelowIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); else if(ListParam[0].Text=="The bar closes above the Vidya Moving Average") BarClosesAboveIndicatorLogic(firstBar,previous,adMA,Component[1],Component[2]); } } //+------------------------------------------------------------------+ class IndicatorManager { public: Indicator *CreateIndicator(string indicatorName,SlotTypes slotType); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Indicator *IndicatorManager::CreateIndicator(string indicatorName,SlotTypes slotType) { if(indicatorName == "Day of Week") return new DaysOfWeek(slotType); if(indicatorName == "Enter Once") return new EnterOnce(slotType); if(indicatorName == "Entry Time") return new EntryTime(slotType); if(indicatorName == "Hourly High Low") return new HourlyHighLow(slotType); if(indicatorName == "Overbought Oversold Index") return new OverboughtOversoldIndex(slotType); if(indicatorName == "Previous High Low") return new PreviousHighLow(slotType); if(indicatorName == "Take Profit") return new TakeProfit(slotType); if (indicatorName == "Vidya Moving Average") return new VidyaMovingAverage(slotType); return NULL; } //+------------------------------------------------------------------+ class IndicatorSlot { public: // Constructors IndicatorSlot(); ~IndicatorSlot(); // Properties int SlotNumber; SlotTypes SlotType; string IndicatorName; string LogicalGroup; int SignalShift; int SignalRepeat; string IndicatorSymbol; DataPeriod IndicatorPeriod; Indicator *IndicatorPointer; // Methods bool GetUsePreviousBarValue(void); string LogicalGroupToString(void); string AdvancedParamsToString(void); string GetIndicatorSymbol(string baseSymbol); DataPeriod GetIndicatorPeriod(DataPeriod basePeriod); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ IndicatorSlot::IndicatorSlot(void) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ IndicatorSlot::~IndicatorSlot(void) { if(CheckPointer(IndicatorPointer)==POINTER_DYNAMIC) delete IndicatorPointer; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IndicatorSlot::GetUsePreviousBarValue(void) { for(int i=0; i0) Slot[i].IndicatorPointer.ShiftSignal(Slot[i].SignalShift); if(Slot[i].SignalRepeat>0) Slot[i].IndicatorPointer.RepeatSignal(Slot[i].SignalRepeat); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Strategy::IsUsingLogicalGroups() { bool isUsingGroups=false; for(int slot=0; slot1) return (true); } return (false); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Strategy::GetDefaultGroup(int slotNumber) { string group=""; SlotTypes slotType=GetSlotType(slotNumber); if(slotType==SlotTypes_OpenFilter) { bool isDefault=Slot[slotNumber].IndicatorPointer.IsDeafultGroupAll || Slot[slotNumber].IndicatorPointer.IsDefaultGroupAll; group=isDefault ? "All" : "A"; } else if(slotType==SlotTypes_CloseFilter) { int index=slotNumber-CloseSlotNumber()-1; group=IntegerToString('a'+index); } return (group); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Strategy::DynamicInfoInitArrays(string ¶ms[],string &values[]) { ArrayResize(params,200); ArrayResize(values,200); for(int i=0; i<200; i++) { params[i] = ""; values[i] = ""; } int index=-2; for(int slot=0; slot 0; strategy.Description = "Exported on 1/12/2018 from Forex Strategy Builder Professional, v3.8.6"; strategy.RecommendedBars = 1000; strategy.FirstBar = 71; strategy.MinBarsRequired = 72; 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 = "Previous High Low"; 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("Previous High Low", 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 long at the previous high"; strategy.Slot[0].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[0].IndicatorPointer.ListParam[1].Caption = "Base price"; strategy.Slot[0].IndicatorPointer.ListParam[1].Index = 0; strategy.Slot[0].IndicatorPointer.ListParam[1].Text = "High & Low"; strategy.Slot[0].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[0].IndicatorPointer.NumParam[0].Caption = "Vertical shift"; 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 = "Overbought Oversold Index"; 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("Overbought Oversold Index", 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 = 5; strategy.Slot[1].IndicatorPointer.ListParam[0].Text = "Overbought Oversold Index crosses the Level line downward"; strategy.Slot[1].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[0].Caption = "Period"; strategy.Slot[1].IndicatorPointer.NumParam[0].Value = Slot1IndParam0; strategy.Slot[1].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[1].Caption = "Level"; strategy.Slot[1].IndicatorPointer.NumParam[1].Value = Slot1IndParam1; 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 = true; strategy.Slot[2].IndicatorName = "Vidya 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("Vidya 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 = 0; strategy.Slot[2].IndicatorPointer.ListParam[0].Text = "The Vidya Moving Average rises"; strategy.Slot[2].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[2].IndicatorPointer.ListParam[2].Caption = "Base price"; strategy.Slot[2].IndicatorPointer.ListParam[2].Index = 3; strategy.Slot[2].IndicatorPointer.ListParam[2].Text = "Close"; strategy.Slot[2].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[0].Caption = "Period"; strategy.Slot[2].IndicatorPointer.NumParam[0].Value = Slot2IndParam0; strategy.Slot[2].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[1].Caption = "Smooth"; 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 = "Enter Once"; 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 = "All"; strategy.Slot[3].IndicatorPointer = indicatorManager.CreateIndicator("Enter Once", SlotTypes_OpenFilter); strategy.Slot[3].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[3].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[3].IndicatorPointer.ListParam[0].Text = "Enter no more than once a bar"; strategy.Slot[4].IndicatorName = "Enter Once"; strategy.Slot[4].SlotType = SlotTypes_OpenFilter; strategy.Slot[4].SignalShift = 0; strategy.Slot[4].SignalRepeat = 0; strategy.Slot[4].IndicatorPeriod = DataPeriod_M1; strategy.Slot[4].IndicatorSymbol = ""; strategy.Slot[4].LogicalGroup = "All"; strategy.Slot[4].IndicatorPointer = indicatorManager.CreateIndicator("Enter Once", SlotTypes_OpenFilter); strategy.Slot[4].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[4].IndicatorPointer.ListParam[0].Index = 1; strategy.Slot[4].IndicatorPointer.ListParam[0].Text = "Enter no more than once a day"; strategy.Slot[5].IndicatorName = "Entry Time"; strategy.Slot[5].SlotType = SlotTypes_OpenFilter; strategy.Slot[5].SignalShift = 0; strategy.Slot[5].SignalRepeat = 0; strategy.Slot[5].IndicatorPeriod = DataPeriod_M1; strategy.Slot[5].IndicatorSymbol = ""; strategy.Slot[5].LogicalGroup = "All"; strategy.Slot[5].IndicatorPointer = indicatorManager.CreateIndicator("Entry Time", SlotTypes_OpenFilter); strategy.Slot[5].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[5].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[5].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[5].IndicatorPointer.ListParam[0].Text = "Enter the market between the specified hours"; strategy.Slot[5].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[0].Caption = "From hour (incl.)"; strategy.Slot[5].IndicatorPointer.NumParam[0].Value = Slot5IndParam0; strategy.Slot[5].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[1].Caption = "From min (incl.)"; strategy.Slot[5].IndicatorPointer.NumParam[1].Value = Slot5IndParam1; strategy.Slot[5].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[2].Caption = "Until hour (excl.)"; strategy.Slot[5].IndicatorPointer.NumParam[2].Value = Slot5IndParam2; strategy.Slot[5].IndicatorPointer.NumParam[3].Enabled = true; strategy.Slot[5].IndicatorPointer.NumParam[3].Caption = "Until min (excl.)"; strategy.Slot[5].IndicatorPointer.NumParam[3].Value = Slot5IndParam3; strategy.Slot[6].IndicatorName = "Day of Week"; strategy.Slot[6].SlotType = SlotTypes_OpenFilter; strategy.Slot[6].SignalShift = 0; strategy.Slot[6].SignalRepeat = 0; strategy.Slot[6].IndicatorPeriod = DataPeriod_M1; strategy.Slot[6].IndicatorSymbol = ""; strategy.Slot[6].LogicalGroup = "All"; strategy.Slot[6].IndicatorPointer = indicatorManager.CreateIndicator("Day of Week", SlotTypes_OpenFilter); strategy.Slot[6].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[6].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[6].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[6].IndicatorPointer.ListParam[0].Text = "Enter the market between the specified days"; strategy.Slot[6].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[6].IndicatorPointer.ListParam[1].Caption = "From (incl.)"; strategy.Slot[6].IndicatorPointer.ListParam[1].Index = 1; strategy.Slot[6].IndicatorPointer.ListParam[1].Text = "Monday"; strategy.Slot[6].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[6].IndicatorPointer.ListParam[2].Caption = "To (excl.)"; strategy.Slot[6].IndicatorPointer.ListParam[2].Index = 4; strategy.Slot[6].IndicatorPointer.ListParam[2].Text = "Thursday"; strategy.Slot[7].IndicatorName = "Hourly High Low"; strategy.Slot[7].SlotType = SlotTypes_OpenFilter; strategy.Slot[7].SignalShift = 0; strategy.Slot[7].SignalRepeat = 0; strategy.Slot[7].IndicatorPeriod = DataPeriod_M1; strategy.Slot[7].IndicatorSymbol = ""; strategy.Slot[7].LogicalGroup = "A"; strategy.Slot[7].IndicatorPointer = indicatorManager.CreateIndicator("Hourly High Low", SlotTypes_OpenFilter); strategy.Slot[7].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[7].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[7].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[7].IndicatorPointer.ListParam[0].Text = "The position opens above the hourly high"; strategy.Slot[7].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[7].IndicatorPointer.ListParam[1].Caption = "Base price"; strategy.Slot[7].IndicatorPointer.ListParam[1].Index = 0; strategy.Slot[7].IndicatorPointer.ListParam[1].Text = "High and Low"; strategy.Slot[7].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[7].IndicatorPointer.NumParam[0].Caption = "Start hour (incl.)"; strategy.Slot[7].IndicatorPointer.NumParam[0].Value = Slot7IndParam0; strategy.Slot[7].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[7].IndicatorPointer.NumParam[1].Caption = "Start minutes (incl.)"; strategy.Slot[7].IndicatorPointer.NumParam[1].Value = Slot7IndParam1; strategy.Slot[7].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[7].IndicatorPointer.NumParam[2].Caption = "End hour (excl.)"; strategy.Slot[7].IndicatorPointer.NumParam[2].Value = Slot7IndParam2; strategy.Slot[7].IndicatorPointer.NumParam[3].Enabled = true; strategy.Slot[7].IndicatorPointer.NumParam[3].Caption = "End minutes (excl.)"; strategy.Slot[7].IndicatorPointer.NumParam[3].Value = Slot7IndParam3; strategy.Slot[7].IndicatorPointer.NumParam[4].Enabled = true; strategy.Slot[7].IndicatorPointer.NumParam[4].Caption = "Vertical shift"; strategy.Slot[7].IndicatorPointer.NumParam[4].Value = Slot7IndParam4; strategy.Slot[8].IndicatorName = "Take Profit"; strategy.Slot[8].SlotType = SlotTypes_Close; strategy.Slot[8].SignalShift = 0; strategy.Slot[8].SignalRepeat = 0; strategy.Slot[8].IndicatorPeriod = DataPeriod_M1; strategy.Slot[8].IndicatorSymbol = ""; strategy.Slot[8].LogicalGroup = ""; strategy.Slot[8].IndicatorPointer = indicatorManager.CreateIndicator("Take Profit", SlotTypes_Close); strategy.Slot[8].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[8].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[8].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[8].IndicatorPointer.ListParam[0].Text = "Exit at Take Profit level"; strategy.Slot[8].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[8].IndicatorPointer.NumParam[0].Caption = "Take Profit"; strategy.Slot[8].IndicatorPointer.NumParam[0].Value = Slot8IndParam0; delete indicatorManager; return strategy; } //+------------------------------------------------------------------+ #define OP_FLAT -1 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Position { public: // Constructors Position(void); // Properties int PosType; PosDirection Direction; double Lots; datetime OpenTime; double OpenPrice; double StopLossPrice; double TakeProfitPrice; double Profit; double Commission; long Ticket; string PosComment; // Methods string ToString(); void SetPositionInfo(string &positionInfo[]); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Position::Position(void) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Position::ToString() { if(PosType==OP_FLAT) return ("Position: Flat"); string text = "Position: " + "Time=" + TimeToString(OpenTime,TIME_SECONDS) +", "+ "Type=" + (PosType==OP_BUY ? "Long" : "Short") +", "+ "Lots=" + DoubleToString(Lots,2) +", "+ "Price=" + DoubleToString(OpenPrice,_Digits) +", "+ "StopLoss=" + DoubleToString(StopLossPrice,_Digits) +", "+ "TakeProfit=" + DoubleToString(TakeProfitPrice,_Digits) +", "+ "Commission=" + DoubleToString(Commission,2) +", "+ "Profit=" + DoubleToString(Profit,2); if(PosComment!="") text+=", \""+PosComment+"\""; return (text); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Position::SetPositionInfo(string &positionInfo[]) { if(PosType==OP_FLAT) { positionInfo[0] = "Position: Flat"; positionInfo[1] = "."; } else { positionInfo[0]=StringFormat("Position: %s %.2f at %s, Profit %.2f", (PosType==OP_BUY) ? "Long" : "Short", Lots, DoubleToString(OpenPrice,_Digits), Profit); positionInfo[1]=StringFormat("Stop Loss: %s, Take Profit: %s", DoubleToString(StopLossPrice,_Digits), DoubleToString(TakeProfitPrice,_Digits)); } } //+------------------------------------------------------------------+ class Logger { int logLines; int fileHandle; public: string GetLogFileName(string symbol,int dataPeriod,int expertMagic); int CreateLogFile(string fileName); void WriteLogLine(string text); void WriteNewLogLine(string text); void WriteLogRequest(string text,string request); bool IsLogLinesLimitReached(int maxLines); void FlushLogFile(void); void CloseLogFile(void); int CloseExpert(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Logger::GetLogFileName(string symbol,int dataPeriod,int expertMagic) { string time=TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS); StringReplace(time,":",""); StringReplace(time," ","_"); string rnd=IntegerToString(MathRand()); string fileName=symbol+"_"+IntegerToString(dataPeriod)+"_"+ IntegerToString(expertMagic)+"_"+time+"_"+rnd+".log"; return (fileName); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int Logger::CreateLogFile(string fileName) { logLines=0; int handle=FileOpen(fileName,FILE_CSV|FILE_WRITE,","); if(handle>0) fileHandle=handle; else Print("CreateFile: Error while creating log file!"); return (handle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteLogLine(string text) { if(fileHandle <= 0) return; FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text); logLines++; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteNewLogLine(string text) { if(fileHandle <= 0) return; FileWrite(fileHandle,""); FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text); logLines+=2; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteLogRequest(string text,string request) { if(fileHandle <= 0) return; FileWrite(fileHandle,"\n"+text); FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),request); logLines+=3; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::FlushLogFile() { if(fileHandle <= 0) return; FileFlush(fileHandle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::CloseLogFile() { if(fileHandle <= 0) return; WriteNewLogLine(StringFormat("%s Closed.",MQLInfoString(MQL_PROGRAM_NAME))); FileClose(fileHandle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Logger::IsLogLinesLimitReached(int maxLines) { return (logLines > maxLines); } //+------------------------------------------------------------------+ class ActionTrade; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class StrategyTrader { private: ActionTrade *actionTrade; Strategy *strategy; DataMarket *market; double epsilon; bool isEnteredLong; bool isEnteredShort; datetime timeLastEntryBar; datetime barOpenTimeForLastCloseTick; StrategyPriceType openStrPriceType; StrategyPriceType closeStrPriceType; int nBarExit; ExecutionTime openTimeExec; ExecutionTime closeTimeExec; bool useLogicalGroups; DictStringBool *groupsAllowLong; DictStringBool *groupsAllowShort; ListString *openingLogicGroups; ListString *closingLogicGroups; PosDirection GetNewPositionDirection(OrderDirection ordDir,double ordLots,PosDirection posDir,double posLots); TradeDirection AnalyzeEntryPrice(void); TradeDirection AnalyzeEntryDirection(void); void AnalyzeEntryLogicConditions(string group,double buyPrice,double sellPrice,bool &canOpenLong,bool &canOpenShort); double AnalyzeEntrySize(OrderDirection ordDir,PosDirection &newPosDir); TradeDirection AnalyzeExitPrice(void); double TradingSize(double size); int AccountPercentStopPoint(double percent,double lots); TradeDirection AnalyzeExitDirection(void); TradeDirection ReduceDirectionStatus(TradeDirection baseDirection,TradeDirection direction); TradeDirection IncreaseDirectionStatus(TradeDirection baseDirection,TradeDirection direction); TradeDirection GetClosingDirection(TradeDirection baseDirection,IndComponentType compDataType); int GetStopLossPoints(double lots); int GetTakeProfitPoints(void); void DoEntryTrade(TradeDirection tradeDir); bool DoExitTrade(void); public: // Constructor, deconstructor StrategyTrader(ActionTrade *actTrade); ~StrategyTrader(void); // Methods void OnInit(Strategy *strat,DataMarket *dataMarket); void OnDeinit(); void InitTrade(void); TickType GetTickType(bool isNewBar,int closeAdvance); void CalculateTrade(TickType ticktype); bool IsWrongStopsExecution(void); void ResendWrongStops(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::StrategyTrader(ActionTrade *actTrade) { actionTrade=actTrade; epsilon=0.000001; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::~StrategyTrader(void) { actionTrade = NULL; strategy = NULL; market = NULL; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::OnInit(Strategy *strat,DataMarket *dataMarket) { strategy = strat; market = dataMarket; groupsAllowLong = new DictStringBool(); groupsAllowShort = new DictStringBool(); openingLogicGroups = new ListString(); closingLogicGroups = new ListString(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::OnDeinit(void) { delete groupsAllowLong; delete groupsAllowShort; delete openingLogicGroups; delete closingLogicGroups; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TickType StrategyTrader::GetTickType(bool isNewBar,int closeAdvance) { TickType tickType = TickType_Regular; datetime barCloseTime = market.BarTime + market.Period*60; if(isNewBar) { barOpenTimeForLastCloseTick=-1; tickType=TickType_Open; } if(market.TickServerTime>barCloseTime-closeAdvance) { if(barOpenTimeForLastCloseTick==market.BarTime) { tickType=TickType_AfterClose; } else { barOpenTimeForLastCloseTick=market.BarTime; tickType=isNewBar ? TickType_OpenClose : TickType_Close; } } return (tickType); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::CalculateTrade(TickType ticktype) { // Exift bool closeOk=false; if(closeStrPriceType!=StrategyPriceType_CloseAndReverse && (market.PositionDirection==PosDirection_Short || market.PositionDirection==PosDirection_Long)) { if(ticktype==TickType_Open && closeStrPriceType==StrategyPriceType_Close && openStrPriceType!=StrategyPriceType_Close) { // We have missed close at the previous Bar Close TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) { // we have a missed close Order if(DoExitTrade()) actionTrade.UpdateDataMarket(market); } } else if(((closeStrPriceType==StrategyPriceType_Open) && (ticktype==TickType_Open || ticktype==TickType_OpenClose)) || ((closeStrPriceType==StrategyPriceType_Close) && (ticktype==TickType_Close || ticktype==TickType_OpenClose))) { // Exit at Bar Open or Bar Close. TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) { // Close the current position. closeOk=DoExitTrade(); if(closeOk) actionTrade.UpdateDataMarket(market); } } else if(closeStrPriceType==StrategyPriceType_Close && openStrPriceType!=StrategyPriceType_Close && ticktype==TickType_AfterClose) { // Exit at after close tick. TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) closeOk=DoExitTrade(); // Close the current position. } else if(closeStrPriceType==StrategyPriceType_Indicator) { // Exit at an indicator value. TradeDirection priceReached=AnalyzeExitPrice(); if(priceReached==TradeDirection_Long) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Both) { if(market.PositionDirection==PosDirection_Short) closeOk=DoExitTrade(); // Close a short position. } } else if(priceReached==TradeDirection_Short) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Short || direction==TradeDirection_Both) { if(market.PositionDirection==PosDirection_Long) closeOk=DoExitTrade(); // Close a long position. } } else if(priceReached==TradeDirection_Both) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short || direction==TradeDirection_Both) closeOk=DoExitTrade(); // Close the current position. } } } // Checks if we closed a position successfully. if(closeOk && !(openStrPriceType==StrategyPriceType_Close && ticktype==TickType_Close)) return; // This is to prevent new entry after Bar Closing has been executed. if(closeStrPriceType==StrategyPriceType_Close && ticktype==TickType_AfterClose) return; if(((openStrPriceType==StrategyPriceType_Open) && (ticktype==TickType_Open || ticktype==TickType_OpenClose)) || ((openStrPriceType==StrategyPriceType_Close) && (ticktype==TickType_Close || ticktype==TickType_OpenClose))) { // Entry at Bar Open or Bar Close. TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short) DoEntryTrade(direction); } else if(openStrPriceType==StrategyPriceType_Indicator) { // Entry at an indicator value. TradeDirection priceReached=AnalyzeEntryPrice(); if(priceReached==TradeDirection_Long) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Both) DoEntryTrade(TradeDirection_Long); } else if(priceReached==TradeDirection_Short) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Short || direction==TradeDirection_Both) DoEntryTrade(TradeDirection_Short); } else if(priceReached==TradeDirection_Both) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short) DoEntryTrade(direction); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ PosDirection StrategyTrader::GetNewPositionDirection(OrderDirection ordDir,double ordLots, PosDirection posDir,double posLots) { if(ordDir!=OrderDirection_Buy && ordDir!=OrderDirection_Sell) return (PosDirection_None); PosDirection currentDir=posDir; double currentLots=posLots; switch(currentDir) { case PosDirection_Long: if(ordDir==OrderDirection_Buy) return (PosDirection_Long); if(currentLots>ordLots+epsilon) return (PosDirection_Long); return (currentLots < ordLots - epsilon ? PosDirection_Short : PosDirection_None); case PosDirection_Short: if(ordDir==OrderDirection_Sell) return (PosDirection_Short); if(currentLots>ordLots+epsilon) return (PosDirection_Short); return (currentLots < ordLots - epsilon ? PosDirection_Long : PosDirection_None); } return (ordDir == OrderDirection_Buy ? PosDirection_Long : PosDirection_Short); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::InitTrade() { openTimeExec=strategy.Slot[0].IndicatorPointer.ExecTime; openStrPriceType=StrategyPriceType_Unknown; if(openTimeExec==ExecutionTime_AtBarOpening) openStrPriceType=StrategyPriceType_Open; else if(openTimeExec==ExecutionTime_AtBarClosing) openStrPriceType=StrategyPriceType_Close; else openStrPriceType=StrategyPriceType_Indicator; closeTimeExec=strategy.Slot[strategy.CloseSlotNumber()].IndicatorPointer.ExecTime; closeStrPriceType=StrategyPriceType_Unknown; if(closeTimeExec==ExecutionTime_AtBarOpening) closeStrPriceType=StrategyPriceType_Open; else if(closeTimeExec==ExecutionTime_AtBarClosing) closeStrPriceType=StrategyPriceType_Close; else if(closeTimeExec==ExecutionTime_CloseAndReverse) closeStrPriceType=StrategyPriceType_CloseAndReverse; else closeStrPriceType=StrategyPriceType_Indicator; useLogicalGroups=strategy.IsUsingLogicalGroups(); if(useLogicalGroups) { strategy.Slot[0].LogicalGroup="All"; strategy.Slot[strategy.CloseSlotNumber()].LogicalGroup="All"; for(int slot=0; slotoldPrice+epsilon && buyPricebasePrice-epsilon && buyPriceoldPrice+epsilon && sellPricebasePrice-epsilon && sellPrice=TimeDayOfWeek(timeLastEntryBar) && market.BarTimeepsilon; bool canOpenShort=sellPrice>epsilon; if(useLogicalGroups) { for(int i=0; i1 && key!="All") || groupsAllowLong.Count()==1) groupLongEntry=groupLongEntry || value; } bool groupShortEntry=false; for(int i=0; i1 && key!="All") || groupsAllowShort.Count()==1) groupShortEntry=groupShortEntry || value; } canOpenLong=canOpenLong && groupLongEntry && groupsAllowLong.Value("All"); canOpenShort=canOpenShort && groupShortEntry && groupsAllowShort.Value("All"); } else { AnalyzeEntryLogicConditions("A",buyPrice,sellPrice,canOpenLong,canOpenShort); } TradeDirection direction=TradeDirection_None; if(canOpenLong && canOpenShort) direction=TradeDirection_Both; else if(canOpenLong) direction=TradeDirection_Long; else if(canOpenShort) direction=TradeDirection_Short; return (direction); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::AnalyzeEntryLogicConditions(string group,double buyPrice,double sellPrice, bool &canOpenLong,bool &canOpenShort) { for(int slotIndex=0; slotIndex<=strategy.CloseSlotNumber(); slotIndex++) { if(useLogicalGroups && strategy.Slot[slotIndex].LogicalGroup != group && strategy.Slot[slotIndex].LogicalGroup != "All") continue; for(int i=0; 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)); } //+------------------------------------------------------------------+ #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; } /*STRATEGY CODE Forex Strategy Builder Professionalv3.8.6eurusd 15m cS PF5974 dd41Default profileFSB Demo dataEURUSD15NothingClose0.6False0.60.60.6False2Exported on 1/12/2018 from Forex Strategy Builder Professional, v3.8.6100070717220001001000Previous High LowLogic0Enter long at the previous highBase price0High & LowVertical shift-3Use previous bar valueTrue00M1Overbought Oversold IndexLogic5Overbought Oversold Index crosses the Level line downwardPeriod52Level95Use previous bar valueTrue00M1Vidya Moving AverageLogic0The Vidya Moving Average risesBase price3ClosePeriod8Smooth60Use previous bar valueTrue00M1Enter OnceLogic0Enter no more than once a barEnter OnceLogic1Enter no more than once a dayEntry TimeLogic0Enter the market between the specified hoursFrom hour (incl.)0From min (incl.)0Until hour (excl.)24Until min (excl.)0Day of WeekLogic0Enter the market between the specified daysFrom (incl.)1MondayTo (excl.)4Thursday00M1Hourly High LowLogic0The position opens above the hourly highBase price0High and LowStart hour (incl.)0Start minutes (incl.)0End hour (excl.)24End minutes (excl.)0Vertical shift000M1Take ProfitLogic0Exit at Take Profit levelTake Profit181 */ //+------------------------------------------------------------------+