//+--------------------------------------------------------------------+ //| 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 "48.0" #property strict // ----------------------- External variables ----------------------- // static input string StrategyProperties__ = "------------"; // ------ Strategy Properties ------ static input double Entry_Amount = 1; // Amount for a new position [lot] static input double Maximum_Amount = 20; // Maximum position amount [lot] static input double Adding_Amount = 1; // Amount to add on addition [lot] static input double Reducing_Amount = 1; // Amount to close on reduction [lot] input int Stop_Loss = 0; // Stop Loss [point] input int Take_Profit = 0; // Take Profit [point] input int Break_Even = 0; // Break Even [point] static input double Martingale_Multiplier = 0; // Martingale Multiplier static input string IndicatorName1 = "Hourly High Low"; // ------ Indicator parameters ------ input int Slot1IndParam0 = 1; // Start hour (incl.) input int Slot1IndParam1 = 1; // Start minutes (incl.) input int Slot1IndParam2 = 6; // End hour (excl.) input int Slot1IndParam3 = 1; // End minutes (excl.) input int Slot1IndParam4 = -184; // Vertical shift static input string IndicatorName2 = "Stochastics"; // ------ Indicator parameters ------ input int Slot2IndParam0 = 10; // %K period input int Slot2IndParam1 = 5; // Fast %D period input int Slot2IndParam2 = 106; // Slow %D period input int Slot2IndParam3 = 25; // Level static input string IndicatorName3 = "Vidya Moving Average"; // ------ Indicator parameters ------ input int Slot3IndParam0 = 31; // Period input int Slot3IndParam1 = 158; // Smooth static input string IndicatorName4 = "Fractal"; // ------ Indicator parameters ------ input int Slot4IndParam0 = -1403; // Vertical shift static input string ExpertSettings__ = "------------"; // ------ Expert Settings ------ // A unique number of the expert's orders. static input int Expert_Magic = 1013450; // 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 BarOpening : public Indicator { public: BarOpening(SlotTypes slotType); virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void BarOpening::BarOpening(SlotTypes slotType) { SlotType = slotType; IndicatorName = "Bar Opening"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_AtBarOpening; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void BarOpening::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); ArrayResize(Component[0].Value,Data.Bars); Component[0].CompName = "Opening price of the bar"; Component[0].DataType = IndComponentType_OpenPrice; Component[0].FirstBar = 2; ArrayCopy(Component[0].Value,Data.Open); } //+------------------------------------------------------------------+ class Fractal : public Indicator { public: Fractal(SlotTypes slotType); virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Fractal::Fractal(SlotTypes slotType) { SlotType = slotType; IndicatorName = "Fractal"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Fractal::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); double epsiolon=Epsilon(); bool isVisible=ListParam[1].Text=="Visible"; double shift=NumParam[0].Value*Data.Point; const int firstBar=8; double upFractals[]; ArrayResize(upFractals,Data.Bars); ArrayInitialize(upFractals,0); double downFractals[]; ArrayResize(downFractals,Data.Bars); ArrayInitialize(downFractals,0); for(int bar=8; barData.Low[bar-2] && Data.Low[bar]>Data.Low[bar-2]) { // Fractal type 1 if(Data.Low[bar-4]>Data.Low[bar-2] && Data.Low[bar-3]>Data.Low[bar-2]) downFractals[bar+1]=Data.Low[bar-2]; // Fractal type 2 if(Data.Low[bar-5]>Data.Low[bar-2] && Data.Low[bar-4]>Data.Low[bar-2] && MathAbs(Data.Low[bar-3]-Data.Low[bar-2])Data.Low[bar-2] && Data.Low[bar-5] > Data.Low[bar-2] && MathAbs(Data.Low[bar-4]-Data.Low[bar-2])=Data.Low[bar-2]) downFractals[bar+1]=Data.Low[bar-2]; // Fractal type 5 if(Data.Low[bar-7]>Data.Low[bar-2] && Data.Low[bar-6]>Data.Low[bar-2] && MathAbs(Data.Low[bar-5]-Data.Low[bar-2])Data.Low[bar-2] && MathAbs(Data.Low[bar-3]-Data.Low[bar-2])Data.Low[bar-2] && Data.Low[bar-6]>Data.Low[bar-2] && MathAbs(Data.Low[bar-5]-Data.Low[bar-2])Data.Low[bar-2]) downFractals[bar+1]=Data.Low[bar-2]; // Fractal type 7 if(Data.Low[bar-8]>Data.Low[bar-2] && Data.Low[bar-7]>Data.Low[bar-2] && MathAbs(Data.Low[bar-6]-Data.Low[bar-2])Data.Low[bar-2] && MathAbs(Data.Low[bar-4]-Data.Low[bar-2])Data.Low[bar-2]) downFractals[bar+1]=Data.Low[bar-2]; } } if(isVisible) { for(int bar=firstBar; barData.High[bar-1]) upFractals[bar]=upFractals[bar-1]; if(downFractals[bar]epsiolon) Component[2].Value[bar]=upFractals[bar]+shift; if(downFractals[bar]>epsiolon) Component[3].Value[bar]=downFractals[bar]-shift; } if(ListParam[0].Text=="Enter long at Down Fractal" || ListParam[0].Text=="Exit long at Down Fractal") for(int bar=firstBar; barepsiolon) Component[2].Value[bar]=downFractals[bar]-shift; if(upFractals[bar]>epsiolon) Component[3].Value[bar]=upFractals[bar]+shift; } } //+------------------------------------------------------------------+ class HourlyHighLow : public Indicator { public: HourlyHighLow(SlotTypes slotType) { SlotType=slotType; IndicatorName="Hourly High Low"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void HourlyHighLow::Calculate(DataSet &dataSet) { Data=GetPointer(dataSet); int fromHour = (int) NumParam[0].Value; int fromMin = (int) NumParam[1].Value; int toHour = (int) NumParam[2].Value; int toMin = (int) NumParam[3].Value; int fromTime = fromHour*60 + fromMin; int toTime = toHour*60 + toMin; double shift=NumParam[4].Value*Data.Point; const int firstBar=2; double adHighPrice[]; ArrayResize(adHighPrice,Data.Bars); ArrayInitialize(adHighPrice,0); double adLowPrice[]; ArrayResize(adLowPrice,Data.Bars); ArrayInitialize(adLowPrice,0); double dMinPrice = DBL_MAX; double dMaxPrice = DBL_MIN; adHighPrice[0] = 0; adLowPrice[0] = 0; bool isOnTimePrev=false; for(int bar=1; bar=fromTime && barTimetoTime) isOnTime=barTime>=fromTime || barTime Data.Low[bar]) dMinPrice = Data.Low[bar]; } if(!isOnTime && isOnTimePrev) { adHighPrice[bar]= dMaxPrice; adLowPrice[bar] = dMinPrice; dMaxPrice = DBL_MIN; dMinPrice = DBL_MAX; } else { adHighPrice[bar] = adHighPrice[bar - 1]; adLowPrice[bar] = adLowPrice[bar - 1]; } isOnTimePrev=isOnTime; } double adUpperBand[]; ArrayResize(adUpperBand,Data.Bars); ArrayInitialize(adUpperBand,0); double adLowerBand[]; ArrayResize(adLowerBand,Data.Bars); ArrayInitialize(adLowerBand,0); for(int bar=firstBar; bar max) max = Data.High[bar - i]; if(Data.Low[bar - i] < min) min = Data.Low[bar - i]; } adHighs[bar] = max; adLows[bar] = min; } adHighs[0] = Data.High[0]; adLows[0] = Data.Low[0]; for(int bar=iK; bar max) max = Data.High[bar - i]; if(Data.Low[bar - i] < min) min = Data.Low[bar - i]; } adHighs[bar] = max; adLows[bar] = min; } double adK[]; ArrayResize(adK,Data.Bars); ArrayInitialize(adK,0); for(int bar=iK; 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 == "Bar Opening") return new BarOpening(slotType); if(indicatorName == "Fractal") return new Fractal(slotType); if(indicatorName == "Hourly High Low") return new HourlyHighLow(slotType); if(indicatorName == "Stochastics") return new Stochastics(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 12/1/2018 from Forex Strategy Builder Professional, v3.8.8"; strategy.RecommendedBars = 1000; strategy.FirstBar = 192; strategy.MinBarsRequired = 193; 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 = "Bar Opening"; 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("Bar Opening", SlotTypes_Open); strategy.Slot[0].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[0].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[0].IndicatorPointer.ListParam[0].Index = 0; strategy.Slot[0].IndicatorPointer.ListParam[0].Text = "Enter the market at the beginning of the bar"; 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 = "Open"; strategy.Slot[1].IndicatorName = "Hourly High Low"; 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("Hourly High Low", 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 = 0; strategy.Slot[1].IndicatorPointer.ListParam[0].Text = "The position opens above the hourly high"; strategy.Slot[1].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[1].IndicatorPointer.ListParam[1].Caption = "Base price"; strategy.Slot[1].IndicatorPointer.ListParam[1].Index = 0; strategy.Slot[1].IndicatorPointer.ListParam[1].Text = "High and Low"; strategy.Slot[1].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[0].Caption = "Start hour (incl.)"; strategy.Slot[1].IndicatorPointer.NumParam[0].Value = Slot1IndParam0; strategy.Slot[1].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[1].Caption = "Start minutes (incl.)"; strategy.Slot[1].IndicatorPointer.NumParam[1].Value = Slot1IndParam1; strategy.Slot[1].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[2].Caption = "End hour (excl.)"; strategy.Slot[1].IndicatorPointer.NumParam[2].Value = Slot1IndParam2; strategy.Slot[1].IndicatorPointer.NumParam[3].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[3].Caption = "End minutes (excl.)"; strategy.Slot[1].IndicatorPointer.NumParam[3].Value = Slot1IndParam3; strategy.Slot[1].IndicatorPointer.NumParam[4].Enabled = true; strategy.Slot[1].IndicatorPointer.NumParam[4].Caption = "Vertical shift"; strategy.Slot[1].IndicatorPointer.NumParam[4].Value = Slot1IndParam4; strategy.Slot[2].IndicatorName = "Stochastics"; strategy.Slot[2].SlotType = SlotTypes_OpenFilter; strategy.Slot[2].SignalShift = 0; strategy.Slot[2].SignalRepeat = 0; strategy.Slot[2].IndicatorPeriod = DataPeriod_D1; strategy.Slot[2].IndicatorSymbol = ""; strategy.Slot[2].LogicalGroup = "A"; strategy.Slot[2].IndicatorPointer = indicatorManager.CreateIndicator("Stochastics", 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 = 2; strategy.Slot[2].IndicatorPointer.ListParam[0].Text = "Slow %D is higher than Level line"; strategy.Slot[2].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[2].IndicatorPointer.ListParam[1].Caption = "Smoothing method"; strategy.Slot[2].IndicatorPointer.ListParam[1].Index = 2; strategy.Slot[2].IndicatorPointer.ListParam[1].Text = "Exponential"; strategy.Slot[2].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[0].Caption = "%K period"; strategy.Slot[2].IndicatorPointer.NumParam[0].Value = Slot2IndParam0; strategy.Slot[2].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[1].Caption = "Fast %D period"; strategy.Slot[2].IndicatorPointer.NumParam[1].Value = Slot2IndParam1; strategy.Slot[2].IndicatorPointer.NumParam[2].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[2].Caption = "Slow %D period"; strategy.Slot[2].IndicatorPointer.NumParam[2].Value = Slot2IndParam2; strategy.Slot[2].IndicatorPointer.NumParam[3].Enabled = true; strategy.Slot[2].IndicatorPointer.NumParam[3].Caption = "Level"; strategy.Slot[2].IndicatorPointer.NumParam[3].Value = Slot2IndParam3; 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 = "Vidya Moving Average"; strategy.Slot[3].SlotType = SlotTypes_OpenFilter; strategy.Slot[3].SignalShift = 0; strategy.Slot[3].SignalRepeat = 0; strategy.Slot[3].IndicatorPeriod = DataPeriod_M1; strategy.Slot[3].IndicatorSymbol = ""; strategy.Slot[3].LogicalGroup = "A"; strategy.Slot[3].IndicatorPointer = indicatorManager.CreateIndicator("Vidya Moving Average", SlotTypes_OpenFilter); strategy.Slot[3].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[3].IndicatorPointer.ListParam[0].Index = 1; strategy.Slot[3].IndicatorPointer.ListParam[0].Text = "The Vidya Moving Average falls"; strategy.Slot[3].IndicatorPointer.ListParam[2].Enabled = true; strategy.Slot[3].IndicatorPointer.ListParam[2].Caption = "Base price"; strategy.Slot[3].IndicatorPointer.ListParam[2].Index = 5; strategy.Slot[3].IndicatorPointer.ListParam[2].Text = "Typical"; strategy.Slot[3].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.NumParam[0].Caption = "Period"; strategy.Slot[3].IndicatorPointer.NumParam[0].Value = Slot3IndParam0; strategy.Slot[3].IndicatorPointer.NumParam[1].Enabled = true; strategy.Slot[3].IndicatorPointer.NumParam[1].Caption = "Smooth"; strategy.Slot[3].IndicatorPointer.NumParam[1].Value = Slot3IndParam1; strategy.Slot[3].IndicatorPointer.CheckParam[0].Enabled = true; strategy.Slot[3].IndicatorPointer.CheckParam[0].Caption = "Use previous bar value"; strategy.Slot[3].IndicatorPointer.CheckParam[0].Checked = true; strategy.Slot[4].IndicatorName = "Fractal"; strategy.Slot[4].SlotType = SlotTypes_Close; strategy.Slot[4].SignalShift = 0; strategy.Slot[4].SignalRepeat = 0; strategy.Slot[4].IndicatorPeriod = DataPeriod_M1; strategy.Slot[4].IndicatorSymbol = ""; strategy.Slot[4].LogicalGroup = ""; strategy.Slot[4].IndicatorPointer = indicatorManager.CreateIndicator("Fractal", SlotTypes_Close); strategy.Slot[4].IndicatorPointer.ListParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[0].Caption = "Logic"; strategy.Slot[4].IndicatorPointer.ListParam[0].Index = 1; strategy.Slot[4].IndicatorPointer.ListParam[0].Text = "Exit long at Down Fractal"; strategy.Slot[4].IndicatorPointer.ListParam[1].Enabled = true; strategy.Slot[4].IndicatorPointer.ListParam[1].Caption = "Visibility"; strategy.Slot[4].IndicatorPointer.ListParam[1].Index = 1; strategy.Slot[4].IndicatorPointer.ListParam[1].Text = "Visible or shadowed"; strategy.Slot[4].IndicatorPointer.NumParam[0].Enabled = true; strategy.Slot[4].IndicatorPointer.NumParam[0].Caption = "Vertical shift"; strategy.Slot[4].IndicatorPointer.NumParam[0].Value = Slot4IndParam0; delete indicatorManager; return strategy; } //+------------------------------------------------------------------+ #define OP_FLAT -1 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Position { public: // Constructors Position(void); // Properties int PosType; PosDirection Direction; double Lots; datetime OpenTime; double OpenPrice; double StopLossPrice; double TakeProfitPrice; double Profit; double Commission; long Ticket; string PosComment; // Methods string ToString(); void SetPositionInfo(string &positionInfo[]); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Position::Position(void) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Position::ToString() { if(PosType==OP_FLAT) return ("Position: Flat"); string text = "Position: " + "Time=" + TimeToString(OpenTime,TIME_SECONDS) +", "+ "Type=" + (PosType==OP_BUY ? "Long" : "Short") +", "+ "Lots=" + DoubleToString(Lots,2) +", "+ "Price=" + DoubleToString(OpenPrice,_Digits) +", "+ "StopLoss=" + DoubleToString(StopLossPrice,_Digits) +", "+ "TakeProfit=" + DoubleToString(TakeProfitPrice,_Digits) +", "+ "Commission=" + DoubleToString(Commission,2) +", "+ "Profit=" + DoubleToString(Profit,2); if(PosComment!="") text+=", \""+PosComment+"\""; return (text); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Position::SetPositionInfo(string &positionInfo[]) { if(PosType==OP_FLAT) { positionInfo[0] = "Position: Flat"; positionInfo[1] = "."; } else { positionInfo[0]=StringFormat("Position: %s %.2f at %s, Profit %.2f", (PosType==OP_BUY) ? "Long" : "Short", Lots, DoubleToString(OpenPrice,_Digits), Profit); positionInfo[1]=StringFormat("Stop Loss: %s, Take Profit: %s", DoubleToString(StopLossPrice,_Digits), DoubleToString(TakeProfitPrice,_Digits)); } } //+------------------------------------------------------------------+ class Logger { int logLines; int fileHandle; public: string GetLogFileName(string symbol,int dataPeriod,int expertMagic); int CreateLogFile(string fileName); void WriteLogLine(string text); void WriteNewLogLine(string text); void WriteLogRequest(string text,string request); bool IsLogLinesLimitReached(int maxLines); void FlushLogFile(void); void CloseLogFile(void); int CloseExpert(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string Logger::GetLogFileName(string symbol,int dataPeriod,int expertMagic) { string time=TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS); StringReplace(time,":",""); StringReplace(time," ","_"); string rnd=IntegerToString(MathRand()); string fileName=symbol+"_"+IntegerToString(dataPeriod)+"_"+ IntegerToString(expertMagic)+"_"+time+"_"+rnd+".log"; return (fileName); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int Logger::CreateLogFile(string fileName) { logLines=0; int handle=FileOpen(fileName,FILE_CSV|FILE_WRITE,","); if(handle>0) fileHandle=handle; else Print("CreateFile: Error while creating log file!"); return (handle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteLogLine(string text) { if(fileHandle <= 0) return; FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text); logLines++; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteNewLogLine(string text) { if(fileHandle <= 0) return; FileWrite(fileHandle,""); FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text); logLines+=2; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::WriteLogRequest(string text,string request) { if(fileHandle <= 0) return; FileWrite(fileHandle,"\n"+text); FileWrite(fileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),request); logLines+=3; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::FlushLogFile() { if(fileHandle <= 0) return; FileFlush(fileHandle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Logger::CloseLogFile() { if(fileHandle <= 0) return; WriteNewLogLine(StringFormat("%s Closed.",MQLInfoString(MQL_PROGRAM_NAME))); FileClose(fileHandle); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Logger::IsLogLinesLimitReached(int maxLines) { return (logLines > maxLines); } //+------------------------------------------------------------------+ class ActionTrade; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class StrategyTrader { private: ActionTrade *actionTrade; Strategy *strategy; DataMarket *market; double epsilon; bool isEnteredLong; bool isEnteredShort; datetime timeLastEntryBar; datetime barOpenTimeForLastCloseTick; StrategyPriceType openStrPriceType; StrategyPriceType closeStrPriceType; int nBarExit; ExecutionTime openTimeExec; ExecutionTime closeTimeExec; bool useLogicalGroups; DictStringBool *groupsAllowLong; DictStringBool *groupsAllowShort; ListString *openingLogicGroups; ListString *closingLogicGroups; PosDirection GetNewPositionDirection(OrderDirection ordDir,double ordLots,PosDirection posDir,double posLots); TradeDirection AnalyzeEntryPrice(void); TradeDirection AnalyzeEntryDirection(void); void AnalyzeEntryLogicConditions(string group,double buyPrice,double sellPrice,bool &canOpenLong,bool &canOpenShort); double AnalyzeEntrySize(OrderDirection ordDir,PosDirection &newPosDir); TradeDirection AnalyzeExitPrice(void); double TradingSize(double size); int AccountPercentStopPoint(double percent,double lots); TradeDirection AnalyzeExitDirection(void); TradeDirection ReduceDirectionStatus(TradeDirection baseDirection,TradeDirection direction); TradeDirection IncreaseDirectionStatus(TradeDirection baseDirection,TradeDirection direction); TradeDirection GetClosingDirection(TradeDirection baseDirection,IndComponentType compDataType); int GetStopLossPoints(double lots); int GetTakeProfitPoints(void); void DoEntryTrade(TradeDirection tradeDir); bool DoExitTrade(void); public: // Constructor, deconstructor StrategyTrader(ActionTrade *actTrade); ~StrategyTrader(void); // Methods void OnInit(Strategy *strat,DataMarket *dataMarket); void OnDeinit(); void InitTrade(void); TickType GetTickType(bool isNewBar,int closeAdvance); void CalculateTrade(TickType ticktype); bool IsWrongStopsExecution(void); void ResendWrongStops(void); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::StrategyTrader(ActionTrade *actTrade) { actionTrade=actTrade; epsilon=0.000001; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::~StrategyTrader(void) { actionTrade = NULL; strategy = NULL; market = NULL; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::OnInit(Strategy *strat,DataMarket *dataMarket) { strategy = strat; market = dataMarket; groupsAllowLong = new DictStringBool(); groupsAllowShort = new DictStringBool(); openingLogicGroups = new ListString(); closingLogicGroups = new ListString(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::OnDeinit(void) { delete groupsAllowLong; delete groupsAllowShort; delete openingLogicGroups; delete closingLogicGroups; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TickType StrategyTrader::GetTickType(bool isNewBar,int closeAdvance) { TickType tickType = TickType_Regular; datetime barCloseTime = market.BarTime + market.Period*60; if(isNewBar) { barOpenTimeForLastCloseTick=-1; tickType=TickType_Open; } if(market.TickServerTime>barCloseTime-closeAdvance) { if(barOpenTimeForLastCloseTick==market.BarTime) { tickType=TickType_AfterClose; } else { barOpenTimeForLastCloseTick=market.BarTime; tickType=isNewBar ? TickType_OpenClose : TickType_Close; } } return (tickType); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::CalculateTrade(TickType ticktype) { // Exift bool closeOk=false; if(closeStrPriceType!=StrategyPriceType_CloseAndReverse && (market.PositionDirection==PosDirection_Short || market.PositionDirection==PosDirection_Long)) { if(ticktype==TickType_Open && closeStrPriceType==StrategyPriceType_Close && openStrPriceType!=StrategyPriceType_Close) { // We have missed close at the previous Bar Close TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) { // we have a missed close Order if(DoExitTrade()) actionTrade.UpdateDataMarket(market); } } else if(((closeStrPriceType==StrategyPriceType_Open) && (ticktype==TickType_Open || ticktype==TickType_OpenClose)) || ((closeStrPriceType==StrategyPriceType_Close) && (ticktype==TickType_Close || ticktype==TickType_OpenClose))) { // Exit at Bar Open or Bar Close. TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) { // Close the current position. closeOk=DoExitTrade(); if(closeOk) actionTrade.UpdateDataMarket(market); } } else if(closeStrPriceType==StrategyPriceType_Close && openStrPriceType!=StrategyPriceType_Close && ticktype==TickType_AfterClose) { // Exit at after close tick. TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Both || (direction == TradeDirection_Long && market.PositionDirection == PosDirection_Short) || (direction == TradeDirection_Short && market.PositionDirection == PosDirection_Long)) closeOk=DoExitTrade(); // Close the current position. } else if(closeStrPriceType==StrategyPriceType_Indicator) { // Exit at an indicator value. TradeDirection priceReached=AnalyzeExitPrice(); if(priceReached==TradeDirection_Long) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Both) { if(market.PositionDirection==PosDirection_Short) closeOk=DoExitTrade(); // Close a short position. } } else if(priceReached==TradeDirection_Short) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Short || direction==TradeDirection_Both) { if(market.PositionDirection==PosDirection_Long) closeOk=DoExitTrade(); // Close a long position. } } else if(priceReached==TradeDirection_Both) { TradeDirection direction=AnalyzeExitDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short || direction==TradeDirection_Both) closeOk=DoExitTrade(); // Close the current position. } } } // Checks if we closed a position successfully. if(closeOk && !(openStrPriceType==StrategyPriceType_Close && ticktype==TickType_Close)) return; // This is to prevent new entry after Bar Closing has been executed. if(closeStrPriceType==StrategyPriceType_Close && ticktype==TickType_AfterClose) return; if(((openStrPriceType==StrategyPriceType_Open) && (ticktype==TickType_Open || ticktype==TickType_OpenClose)) || ((openStrPriceType==StrategyPriceType_Close) && (ticktype==TickType_Close || ticktype==TickType_OpenClose))) { // Entry at Bar Open or Bar Close. TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short) DoEntryTrade(direction); } else if(openStrPriceType==StrategyPriceType_Indicator) { // Entry at an indicator value. TradeDirection priceReached=AnalyzeEntryPrice(); if(priceReached==TradeDirection_Long) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Both) DoEntryTrade(TradeDirection_Long); } else if(priceReached==TradeDirection_Short) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Short || direction==TradeDirection_Both) DoEntryTrade(TradeDirection_Short); } else if(priceReached==TradeDirection_Both) { TradeDirection direction=AnalyzeEntryDirection(); if(direction==TradeDirection_Long || direction==TradeDirection_Short) DoEntryTrade(direction); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ PosDirection StrategyTrader::GetNewPositionDirection(OrderDirection ordDir,double ordLots, PosDirection posDir,double posLots) { if(ordDir!=OrderDirection_Buy && ordDir!=OrderDirection_Sell) return (PosDirection_None); PosDirection currentDir=posDir; double currentLots=posLots; switch(currentDir) { case PosDirection_Long: if(ordDir==OrderDirection_Buy) return (PosDirection_Long); if(currentLots>ordLots+epsilon) return (PosDirection_Long); return (currentLots < ordLots - epsilon ? PosDirection_Short : PosDirection_None); case PosDirection_Short: if(ordDir==OrderDirection_Sell) return (PosDirection_Short); if(currentLots>ordLots+epsilon) return (PosDirection_Short); return (currentLots < ordLots - epsilon ? PosDirection_Long : PosDirection_None); } return (ordDir == OrderDirection_Buy ? PosDirection_Long : PosDirection_Short); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::InitTrade() { openTimeExec=strategy.Slot[0].IndicatorPointer.ExecTime; openStrPriceType=StrategyPriceType_Unknown; if(openTimeExec==ExecutionTime_AtBarOpening) openStrPriceType=StrategyPriceType_Open; else if(openTimeExec==ExecutionTime_AtBarClosing) openStrPriceType=StrategyPriceType_Close; else openStrPriceType=StrategyPriceType_Indicator; closeTimeExec=strategy.Slot[strategy.CloseSlotNumber()].IndicatorPointer.ExecTime; closeStrPriceType=StrategyPriceType_Unknown; if(closeTimeExec==ExecutionTime_AtBarOpening) closeStrPriceType=StrategyPriceType_Open; else if(closeTimeExec==ExecutionTime_AtBarClosing) closeStrPriceType=StrategyPriceType_Close; else if(closeTimeExec==ExecutionTime_CloseAndReverse) closeStrPriceType=StrategyPriceType_CloseAndReverse; else closeStrPriceType=StrategyPriceType_Indicator; useLogicalGroups=strategy.IsUsingLogicalGroups(); if(useLogicalGroups) { strategy.Slot[0].LogicalGroup="All"; strategy.Slot[strategy.CloseSlotNumber()].LogicalGroup="All"; for(int slot=0; slotoldPrice+epsilon && buyPricebasePrice-epsilon && buyPriceoldPrice+epsilon && sellPricebasePrice-epsilon && sellPrice=TimeDayOfWeek(timeLastEntryBar) && market.BarTimeepsilon; bool canOpenShort=sellPrice>epsilon; if(useLogicalGroups) { for(int i=0; i1 && key!="All") || groupsAllowLong.Count()==1) groupLongEntry=groupLongEntry || value; } bool groupShortEntry=false; for(int i=0; i1 && key!="All") || groupsAllowShort.Count()==1) groupShortEntry=groupShortEntry || value; } canOpenLong=canOpenLong && groupLongEntry && groupsAllowLong.Value("All"); canOpenShort=canOpenShort && groupShortEntry && groupsAllowShort.Value("All"); } else { AnalyzeEntryLogicConditions("A",buyPrice,sellPrice,canOpenLong,canOpenShort); } TradeDirection direction=TradeDirection_None; if(canOpenLong && canOpenShort) direction=TradeDirection_Both; else if(canOpenLong) direction=TradeDirection_Long; else if(canOpenShort) direction=TradeDirection_Short; return (direction); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void StrategyTrader::AnalyzeEntryLogicConditions(string group,double buyPrice,double sellPrice, bool &canOpenLong,bool &canOpenShort) { for(int slotIndex=0; slotIndex<=strategy.CloseSlotNumber(); slotIndex++) { if(useLogicalGroups && strategy.Slot[slotIndex].LogicalGroup != group && strategy.Slot[slotIndex].LogicalGroup != "All") continue; for(int i=0; i epsilon) { switch(component.PosPriceDependence) { case PositionPriceDependence_PriceBuyHigher: canOpenLong=canOpenLong && buyPrice>indicatorValue+epsilon; break; case PositionPriceDependence_PriceBuyLower: canOpenLong=canOpenLong && buyPriceindicatorValue+epsilon; break; case PositionPriceDependence_PriceSellLower: canOpenShort=canOpenShort && sellPrice indicatorValue + epsilon; canOpenShort = canOpenShort && sellPrice < indicatorValue - epsilon; break; case PositionPriceDependence_BuyLowerSelHigher: // Deprecated case PositionPriceDependence_BuyLowerSellHigher: canOpenLong = canOpenLong && buyPrice < indicatorValue - epsilon; canOpenShort = canOpenShort && sellPrice > indicatorValue + epsilon; break; } } else { canOpenLong = false; canOpenShort = false; } } component=NULL; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double StrategyTrader::AnalyzeEntrySize(OrderDirection ordDir,PosDirection &newPosDir) { double size=0; PosDirection posDir=market.PositionDirection; // Orders modification on a fly // Checks whether we are on the market if(posDir==PosDirection_Long || posDir==PosDirection_Short) { // We are on the market and have Same Dir Signal if((ordDir==OrderDirection_Buy && posDir==PosDirection_Long) || (ordDir==OrderDirection_Sell && posDir==PosDirection_Short)) { size=0; newPosDir=posDir; if(market.PositionLots+TradingSize(strategy.AddingLots)< strategy.MaxOpenLots+market.LotStep/2) { switch(strategy.SameSignalAction) { case SameDirSignalAction_Add: size=TradingSize(strategy.AddingLots); break; case SameDirSignalAction_Winner: if(market.PositionProfit>epsilon) size=TradingSize(strategy.AddingLots); break; case SameDirSignalAction_Loser: if(market.PositionProfit<-epsilon) size=TradingSize(strategy.AddingLots); break; } } } else if((ordDir==OrderDirection_Buy && posDir==PosDirection_Short) || (ordDir==OrderDirection_Sell && posDir==PosDirection_Long)) { // In case of an Opposite Dir Signal switch(strategy.OppSignalAction) { case OppositeDirSignalAction_Reduce: if(market.PositionLots>TradingSize(strategy.ReducingLots)) { // Reducing size=TradingSize(strategy.ReducingLots); newPosDir=posDir; } else { // Closing size=market.PositionLots; newPosDir=PosDirection_Closed; } break; case OppositeDirSignalAction_Close: size=market.PositionLots; newPosDir=PosDirection_Closed; break; case OppositeDirSignalAction_Reverse: size=market.PositionLots+TradingSize(strategy.EntryLots); newPosDir=(posDir==PosDirection_Long) ? PosDirection_Short : PosDirection_Long; break; case OppositeDirSignalAction_Nothing: size=0; newPosDir=posDir; break; } } } else { // We are square on the market size=TradingSize(strategy.EntryLots); if(strategy.UseMartingale && market.ConsecutiveLosses>0) { double correctedAmount=size*MathPow(strategy.MartingaleMultiplier,market.ConsecutiveLosses); double normalizedAmount=actionTrade.NormalizeEntrySize(correctedAmount); size=MathMax(normalizedAmount,market.MinLot); } size=MathMin(size,strategy.MaxOpenLots); newPosDir=(ordDir==OrderDirection_Buy) ? PosDirection_Long : PosDirection_Short; } return (size); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::AnalyzeExitPrice() { IndicatorSlot *slot=strategy.Slot[strategy.CloseSlotNumber()]; // Searching the exit price in the exit indicator slot. double buyPrice=0; double sellPrice=0; for(int i=0; iepsilon; bool canCloseShort=buyPrice>epsilon; // Check if the closing price was reached. if(canCloseLong) { canCloseLong=(sellPrice>market.OldBid+epsilon && sellPricemarket.Bid-epsilon); } if(canCloseShort) { canCloseShort=(buyPrice>market.OldBid+epsilon && buyPricemarket.Bid-epsilon); } // Determine the trading direction. TradeDirection direction=TradeDirection_None; if(canCloseLong && canCloseShort) direction=TradeDirection_Both; else if(canCloseLong) direction=TradeDirection_Short; else if(canCloseShort) direction=TradeDirection_Long; slot=NULL; return (direction); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::AnalyzeExitDirection() { int closeSlot=strategy.CloseSlotNumber(); if(closeTimeExec==ExecutionTime_AtBarClosing) for(int i=0; i0 && (market.PositionOpenTime+(nBarExit *((int) market.Period*60))0) slotDirection=GetClosingDirection(slotDirection,strategy.Slot[slot].IndicatorPointer.Component[c].DataType); } groupDirection=ReduceDirectionStatus(groupDirection,slotDirection); } } direction=IncreaseDirectionStatus(direction,groupDirection); } } else { // Search close filters for a closing signal. for(int slot=strategy.CloseSlotNumber()+1; slotepsilon) direction=GetClosingDirection(direction,strategy.Slot[slot].IndicatorPointer.Component[c].DataType); } } } return (direction); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::ReduceDirectionStatus(TradeDirection baseDirection,TradeDirection direction) { if(baseDirection==direction || direction==TradeDirection_Both) return (baseDirection); if(baseDirection==TradeDirection_Both) return (direction); return (TradeDirection_None); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::IncreaseDirectionStatus(TradeDirection baseDirection,TradeDirection direction) { if(baseDirection==direction || direction==TradeDirection_None) return (baseDirection); if(baseDirection==TradeDirection_None) return (direction); return (TradeDirection_Both); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ TradeDirection StrategyTrader::GetClosingDirection(TradeDirection baseDirection,IndComponentType compDataType) { TradeDirection newDirection=baseDirection; if(compDataType==IndComponentType_ForceClose) { newDirection=TradeDirection_Both; } else if(compDataType==IndComponentType_ForceCloseShort) { if(baseDirection == TradeDirection_None) newDirection = TradeDirection_Long; else if(baseDirection==TradeDirection_Short) newDirection=TradeDirection_Both; } else if(compDataType==IndComponentType_ForceCloseLong) { if(baseDirection == TradeDirection_None) newDirection = TradeDirection_Short; else if(baseDirection==TradeDirection_Long) newDirection=TradeDirection_Both; } return (newDirection); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int StrategyTrader::GetStopLossPoints(double lots) { int indStop = INT_MAX; bool isIndStop = true; int closeSlot = strategy.CloseSlotNumber(); string name=strategy.Slot[closeSlot].IndicatorName; if(name=="Account Percent Stop") indStop=AccountPercentStopPoint(strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value,lots); else if(name== "ATR Stop") indStop =(int) MathRound(strategy.Slot[closeSlot].IndicatorPointer.Component[0].GetLastValue()/market.Point); else if(name== "Stop Loss"|| name == "Stop Limit") indStop =(int) strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value; else if(name== "Trailing Stop"|| name == "Trailing Stop Limit") indStop =(int) strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value; else isIndStop=false; int permStop = strategy.UsePermanentSL ? strategy.PermanentSL : INT_MAX; int stopLoss = 0; if(isIndStop || strategy.UsePermanentSL) { stopLoss=MathMin(indStop,permStop); if(stopLoss=maxRetry) { market.WrongStopLoss = 0; market.WrongTakeProf = 0; market.WrongStopsRetry = 0; return (false); } bool isWrongStop=(market.WrongStopLoss>0 && market.PositionStopLoss0 && market.PositionTakeProfit0) { if(market.PositionDirection==PosDirection_Long) stopLossPrice=market.Bid-stopLoss*market.Point; else if(market.PositionDirection==PosDirection_Short) stopLossPrice=market.Ask+stopLoss*market.Point; } double takeProfitPrice=0; int takeProfit=market.WrongTakeProf; if(takeProfit>0) { if(market.PositionDirection==PosDirection_Long) takeProfitPrice=market.Bid+takeProfit*market.Point; else if(market.PositionDirection==PosDirection_Short) takeProfitPrice=market.Ask-takeProfit*market.Point; } bool isSucess=actionTrade.ModifyPosition(stopLossPrice,takeProfitPrice); if(isSucess) { market.WrongStopLoss = 0; market.WrongTakeProf = 0; market.WrongStopsRetry = 0; } else { market.WrongStopsRetry++; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double StrategyTrader::TradingSize(double size) { if(strategy.UseAccountPercentEntry) size=(size/100)*market.AccountEquity/market.MarginRequired; if(size>strategy.MaxOpenLots) size=strategy.MaxOpenLots; return (actionTrade.NormalizeEntrySize(size)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int StrategyTrader::AccountPercentStopPoint(double percent,double lots) { double balance = market.AccountBalance; double moneyrisk = balance * percent / 100; double spread = market.Spread; double tickvalue = market.TickValue; double stoploss = moneyrisk / (lots * tickvalue) - spread; return ((int) MathRound(stoploss)); } //+------------------------------------------------------------------+ #define TRADE_RETRY_COUNT 4 #define TRADE_RETRY_WAIT 100 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class ActionTrade { private: double epsilon; // Fields Strategy *strategy; DataSet *dataSet[]; DataMarket *dataMarket; Position *position; Logger *logger; StrategyTrader *strategyTrader; // 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.8EURUSD 1Hr SPRD2.0 fractal trailing 10kto600k PF2.9 DD21 2015-18Default profileFSB Demo dataGBPUSD60WinnerReverse20False111False2Exported on 12/1/2018 from Forex Strategy Builder Professional, v3.8.8100030192193100010001000Bar OpeningLogic0Enter the market at the beginning of the barBase price0OpenHourly High LowLogic0The position opens above the hourly highBase price0High and LowStart hour (incl.)1Start minutes (incl.)1End hour (excl.)6End minutes (excl.)1Vertical shift-18400M1StochasticsLogic2Slow %D is higher than Level lineSmoothing method2Exponential%K period10Fast %D period5Slow %D period106Level25Use previous bar valueTrue00D1Vidya Moving AverageLogic1The Vidya Moving Average fallsBase price5TypicalPeriod31Smooth158Use previous bar valueTrue00M1FractalLogic1Exit long at Down FractalVisibility1Visible or shadowedVertical shift-140300M1 */ //+------------------------------------------------------------------+