//+--------------------------------------------------------------------+
//| Copyright: (C) 2014 |
//| |
//| 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) 2014 Forex Software Ltd."
#property link "http://forexsb.com"
#property version "27.0"
#property strict
// ----------------------- External variables ----------------------- //
extern double Entry_Amount = 1; // Entry amount for a new position [lot]
extern double Maximum_Amount = 20; // Maximum position amount [lot]
extern double Adding_Amount = 1; // Amount to add on addition [lot]
extern double Reducing_Amount = 1; // Amount to close on reduction [lot]
// 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).
extern 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.
extern int Protection_Max_StopLoss=0; // Ensure maximum Stop Loss [point]
// How many seconds before the expected bar closing to rise a Bar Closing event.
extern int Bar_Close_Advance=15; // Bar closing advance [sec]
// Expert writes a log file when Write_Log_File = true.
extern bool Write_Log_File=false; // Write a log file
// Custom comment. It can be used for setting a binnary option epxiration perod
extern string Order_Comment=""; // Custom order comment
// ---------------------------- Options ---------------------------- //
// Data bars for calculating the indicator values with the necessary precission.
int Max_Data_Bars=0;
// Have 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
// The expert loads this XML file form MetaTrader "Files" folder if no XML string is provided.
string Strategy_File_Name="Strategy.xml"; // FSB Strategy Name
// The strategy as an XML string. If XML is provide, the expert loads it instead of a file.
string Strategy_XML="Forex Strategy Builder Professionalv3.2.4New StrategyDefault profileFSB Demo dataEURUSD1440NothingNothing20False111False2100010102103100010001000Bar OpeningLogic0Enter the market at the beginning of the barBase price0OpenMoving AverageLogic2The bar opens above Moving AverageSmoothing method2ExponentialBase price3ClosePeriod100Shift0Use previous bar valueTrue00M1Day ClosingLogic0Exit the market at the end of the dayBase price0Close"; // XML String
// 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 number of lines, the expert starts a new file.
int MaxLogLinesInFile=2000;
// Used to detect a chart change
string __symbol = "";
int __period = -1;
//## Import Start
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum DataPeriod
{
DataPeriod_M1 = 1,
DataPeriod_M5 = 5,
DataPeriod_M15 = 15,
DataPeriod_M30 = 30,
DataPeriod_H1 = 60,
DataPeriod_H4 = 240,
DataPeriod_D1 = 1440,
DataPeriod_W1 = 10080,
DataPeriod_MN1 = 43200
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum PosDirection
{
PosDirection_None,
PosDirection_Long,
PosDirection_Short,
PosDirection_Closed
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum OrderDirection
{
OrderDirection_None,
OrderDirection_Buy,
OrderDirection_Sell
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum StrategyPriceType
{
StrategyPriceType_Open,
StrategyPriceType_Close,
StrategyPriceType_Indicator,
StrategyPriceType_CloseAndReverse,
StrategyPriceType_Unknown
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum ExecutionTime
{
ExecutionTime_DuringTheBar,
ExecutionTime_AtBarOpening,
ExecutionTime_AtBarClosing,
ExecutionTime_CloseAndReverse
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum TraderOrderType
{
TraderOrderType_Buy = 0,
TraderOrderType_Sell = 1,
TraderOrderType_BuyLimit = 2,
TraderOrderType_SellLimit = 3,
TraderOrderType_BuyStop = 4,
TraderOrderType_SellStop = 5
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum TradeDirection
{
TradeDirection_None,
TradeDirection_Long,
TradeDirection_Short,
TradeDirection_Both
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum LongTradeEntryPrice
{
LongTradeEntryPrice_Bid,
LongTradeEntryPrice_Ask,
LongTradeEntryPrice_Chart
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum OperationType
{
OperationType_Buy,
OperationType_Sell,
OperationType_Close,
OperationType_Modify
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum TickType
{
TickType_Open = 0,
TickType_OpenClose = 1,
TickType_Regular = 2,
TickType_Close = 3,
TickType_AfterClose = 4
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum InstrumentType
{
InstrumentType_Forex,
InstrumentType_CFD,
InstrumentType_Index
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum SlotTypes
{
SlotTypes_NotDefined = 0,
SlotTypes_Open = 1,
SlotTypes_OpenFilter = 2,
SlotTypes_Close = 4,
SlotTypes_CloseFilter = 8
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum IndComponentType
{
IndComponentType_NotDefined,
IndComponentType_OpenLongPrice,
IndComponentType_OpenShortPrice,
IndComponentType_OpenPrice,
IndComponentType_CloseLongPrice,
IndComponentType_CloseShortPrice,
IndComponentType_ClosePrice,
IndComponentType_OpenClosePrice,
IndComponentType_IndicatorValue,
IndComponentType_AllowOpenLong,
IndComponentType_AllowOpenShort,
IndComponentType_ForceCloseLong,
IndComponentType_ForceCloseShort,
IndComponentType_ForceClose,
IndComponentType_Other
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum PositionPriceDependence
{
PositionPriceDependence_None,
PositionPriceDependence_PriceBuyHigher,
PositionPriceDependence_PriceBuyLower,
PositionPriceDependence_PriceSellHigher,
PositionPriceDependence_PriceSellLower,
PositionPriceDependence_BuyHigherSellLower,
PositionPriceDependence_BuyLowerSelHigher,
PositionPriceDependence_PriceBuyCrossesUpBandInwards,
PositionPriceDependence_PriceBuyCrossesUpBandOutwards,
PositionPriceDependence_PriceBuyCrossesDownBandInwards,
PositionPriceDependence_PriceBuyCrossesDownBandOutwards,
PositionPriceDependence_PriceSellCrossesUpBandInwards,
PositionPriceDependence_PriceSellCrossesUpBandOutwards,
PositionPriceDependence_PriceSellCrossesDownBandInwards,
PositionPriceDependence_PriceSellCrossesDownBandOutwards
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum BasePrice
{
BasePrice_Open = 0,
BasePrice_High = 1,
BasePrice_Low = 2,
BasePrice_Close = 3,
BasePrice_Median = 4, // Price[bar] = (Low[bar] + High[bar]) / 2;
BasePrice_Typical = 5, // Price[bar] = (Low[bar] + High[bar] + Close[bar]) / 3;
BasePrice_Weighted = 6 // Price[bar] = (Low[bar] + High[bar] + 2 * Close[bar]) / 4;
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum MAMethod
{
MAMethod_Simple = 0,
MAMethod_Weighted = 1,
MAMethod_Exponential = 2,
MAMethod_Smoothed = 3
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum SameDirSignalAction
{
SameDirSignalAction_Nothing,
SameDirSignalAction_Add,
SameDirSignalAction_Winner,
SameDirSignalAction_Loser,
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum OppositeDirSignalAction
{
OppositeDirSignalAction_Nothing,
OppositeDirSignalAction_Reduce,
OppositeDirSignalAction_Close,
OppositeDirSignalAction_Reverse
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum PermanentProtectionType
{
PermanentProtectionType_Relative,
PermanentProtectionType_Absolute
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum TrailingStopMode
{
TrailingStopMode_Bar,
TrailingStopMode_Tick
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum IndicatorLogic
{
IndicatorLogic_The_indicator_rises,
IndicatorLogic_The_indicator_falls,
IndicatorLogic_The_indicator_is_higher_than_the_level_line,
IndicatorLogic_The_indicator_is_lower_than_the_level_line,
IndicatorLogic_The_indicator_crosses_the_level_line_upward,
IndicatorLogic_The_indicator_crosses_the_level_line_downward,
IndicatorLogic_The_indicator_changes_its_direction_upward,
IndicatorLogic_The_indicator_changes_its_direction_downward,
IndicatorLogic_The_price_buy_is_higher_than_the_ind_value,
IndicatorLogic_The_price_buy_is_lower_than_the_ind_value,
IndicatorLogic_The_price_open_is_higher_than_the_ind_value,
IndicatorLogic_The_price_open_is_lower_than_the_ind_value,
IndicatorLogic_It_does_not_act_as_a_filter,
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum BandIndLogic
{
BandIndLogic_The_bar_opens_below_the_Upper_Band,
BandIndLogic_The_bar_opens_above_the_Upper_Band,
BandIndLogic_The_bar_opens_below_the_Lower_Band,
BandIndLogic_The_bar_opens_above_the_Lower_Band,
BandIndLogic_The_position_opens_below_the_Upper_Band,
BandIndLogic_The_position_opens_above_the_Upper_Band,
BandIndLogic_The_position_opens_below_the_Lower_Band,
BandIndLogic_The_position_opens_above_the_Lower_Band,
BandIndLogic_The_bar_opens_below_Upper_Band_after_above,
BandIndLogic_The_bar_opens_above_Upper_Band_after_below,
BandIndLogic_The_bar_opens_below_Lower_Band_after_above,
BandIndLogic_The_bar_opens_above_Lower_Band_after_below,
BandIndLogic_The_bar_closes_below_the_Upper_Band,
BandIndLogic_The_bar_closes_above_the_Upper_Band,
BandIndLogic_The_bar_closes_below_the_Lower_Band,
BandIndLogic_The_bar_closes_above_the_Lower_Band,
BandIndLogic_It_does_not_act_as_a_filter
};
//## Import Start
//+------------------------------------------------------------------+
//| Create a text label |
//+------------------------------------------------------------------+
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);
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
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);
}
//+------------------------------------------------------------------+
//| Change the label text |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Delete a text label |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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; istrategyDataSet.Period ? 1 : 0;
NormalizeComponentValue(Component[i].Value,strategyDataSet.Time,value,ltfShift);
ArrayCopy(Component[i].Value,value);
Component[i].FirstBar=NormalizeComponentFirstBar(Component[i].FirstBar,strategyDataSet.Time);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::ShiftSignal(int shift)
{
for(int i=0; i=ltfOpenTime && time=ltfCloseTime)
break;
{return;}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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()
{
for(int i=0; i<10; i++)
if(Component[i].DataType==IndComponentType_NotDefined)
return i;
return 10;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string Indicator::IndicatorParamToString()
{
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;
}
break;
case IndicatorLogic_The_indicator_falls:
for(int bar=firstBar; 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]levelLong+sigma ? 1 : 0;
indCompShort.Value[bar]=adIndValue[bar-prvs] 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-prvs]firstBar)
baseBar--;
indCompLong.Value[bar]=(adIndValue[baseBar]>levelLong+sigma && adIndValue[bar-prvs]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-prvs]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 prvs,const double &adUpperBand[],const double &adLowerBand[],IndicatorComp &indCompLong,IndicatorComp &indCompShort,BandIndLogic indLogic)
{
double sigma=Sigma();
firstBar=MathMax(firstBar,2);
for(int bar=0; baradLowerBand[bar-prvs]+sigma ? 1 : 0;
}
break;
case BandIndLogic_The_bar_opens_above_the_Upper_Band:
for(int bar=firstBar; baradUpperBand[bar-prvs]+sigma ? 1 : 0;
indCompShort.Value[bar]=Data.Open[bar]adUpperBand[bar-prvs]+sigma ? 1 : 0;
}
break;
case BandIndLogic_The_bar_opens_above_the_Lower_Band:
for(int bar=firstBar; baradLowerBand[bar-prvs]+sigma ? 1 : 0;
indCompShort.Value[bar]=Data.Open[bar]firstBar)
baseBar--;
indCompLong.Value[bar]=Data.Open[bar]adUpperBand[baseBar-prvs]+sigma ? 1 : 0;
baseBar=bar-1;
while(MathAbs(Data.Open[baseBar]-adLowerBand[baseBar-prvs])firstBar)
baseBar--;
indCompShort.Value[bar]=Data.Open[bar]>adLowerBand[bar-prvs]+sigma && Data.Open[baseBar]firstBar)
baseBar--;
indCompLong.Value[bar]=Data.Open[bar]>adUpperBand[bar-prvs]+sigma && Data.Open[baseBar]firstBar)
baseBar--;
indCompShort.Value[bar]=Data.Open[bar]adLowerBand[baseBar-prvs]+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-prvs]+sigma ? 1 : 0;
baseBar=bar-1;
while(MathAbs(Data.Open[baseBar]-adUpperBand[baseBar-prvs])firstBar)
baseBar--;
indCompShort.Value[bar]=Data.Open[bar]>adUpperBand[bar-prvs]+sigma && Data.Open[baseBar]firstBar)
baseBar--;
indCompLong.Value[bar]=Data.Open[bar]>adLowerBand[bar-prvs]+sigma && Data.Open[baseBar]firstBar)
baseBar--;
indCompShort.Value[bar]=Data.Open[bar]adUpperBand[baseBar-prvs]+sigma ? 1 : 0;
}
break;
case BandIndLogic_The_bar_closes_below_the_Upper_Band:
for(int bar=firstBar; baradLowerBand[bar-prvs]+sigma ? 1 : 0;
}
break;
case BandIndLogic_The_bar_closes_above_the_Upper_Band:
for(int bar=firstBar; baradUpperBand[bar-prvs]+sigma ? 1 : 0;
indCompShort.Value[bar]=Data.Close[bar]adUpperBand[bar-prvs]+sigma ? 1 : 0;
}
break;
case BandIndLogic_The_bar_closes_above_the_Lower_Band:
for(int bar=firstBar; baradLowerBand[bar-prvs]+sigma ? 1 : 0;
indCompShort.Value[bar]=Data.Close[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]firstBar)
{
isNoChange=(isLower==(adIndValue[baseBar+1]adIndValue[baseBar]+sigma ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::IndicatorIsHigherThanAnotherIndicatorLogic(int firstBar,int prvs,const double &adIndValue[],double &adAnotherIndValue[],IndicatorComp &indCompLong,IndicatorComp &indCompShort)
{
double sigma=Sigma();
firstBar=MathMax(firstBar,2);
for(int bar=0; baradAnotherIndValue[currentBar]+sigma ? 1 : 0;
indCompShort.Value[bar]=adIndValue[currentBar]adAnotherIndValue[currentBar]+sigma ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::IndicatorChangesItsDirectionUpward(int firstBar,int prvs,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;
indCompShort.Value[bar] = (adIndValue[bar2] < adIndValue[bar1] && adIndValue[bar1] > adIndValue[bar0] && bar1 == bar0 - 1) ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::IndicatorChangesItsDirectionDownward(int firstBar,int prvs,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;
indCompShort.Value[bar] = (adIndValue[bar2] > adIndValue[bar1] && adIndValue[bar1] < adIndValue[bar0] && bar1 == bar0 - 1) ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::IndicatorCrossesAnotherIndicatorUpwardLogic(int firstBar,int prvs,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[currentBar]+sigma && adIndValue[baseBar]adAnotherIndValue[baseBar]+sigma ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::IndicatorCrossesAnotherIndicatorDownwardLogic(int firstBar,int prvs,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-prvs]+sigma ? 1 : 0;
indCompShort.Value[bar]=Data.Open[bar]adIndValue[bar-prvs]+sigma ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::BarOpensAboveIndicatorAfterOpeningBelowLogic(int firstBar,int prvs,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-prvs]+sigma && Data.Open[baseBar]adIndValue[baseBar-prvs]+sigma ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::BarOpensBelowIndicatorAfterOpeningAboveLogic(int firstBar,int prvs,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-prvs]+sigma ? 1 : 0;
indCompShort.Value[bar]=Data.Open[bar]>adIndValue[bar-prvs]+sigma && Data.Open[baseBar] adIndValue[bar - prvs] + sigma ? 1 : 0;
indCompShort.Value[bar] = Data.Close[bar] < adIndValue[bar - prvs] - sigma ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Indicator::BarClosesBelowIndicatorLogic(int firstBar,int prvs,const double &adIndValue[],IndicatorComp &indCompLong,IndicatorComp &indCompShort)
{
double sigma=Sigma();
firstBar=MathMax(firstBar,2);
for(int bar=0; bar adIndValue[bar - prvs] + sigma ? 1 : 0;
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class BarOpening : public Indicator
{
public:
BarOpening(SlotTypes slotType)
{
SlotType=slotType;
IndicatorName="Bar Opening";
WarningMessage = "";
IsAllowLTF = true;
ExecTime = ExecutionTime_AtBarOpening;
IsSeparateChart = false;
IsDiscreteValues = false;
IsDeafultGroupAll = false;
}
virtual void Calculate(DataSet &dataSet);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void BarOpening::Calculate(DataSet &dataSet)
{
Data=GetPointer(dataSet);
// Saving the components
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 DayClosing : public Indicator
{
public:
DayClosing(SlotTypes slotType)
{
SlotType=slotType;
IndicatorName="Day Closing";
WarningMessage = "";
IsAllowLTF = true;
ExecTime = ExecutionTime_AtBarClosing;
IsSeparateChart = false;
IsDiscreteValues = false;
IsDeafultGroupAll = false;
}
virtual void Calculate(DataSet &dataSet);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void DayClosing::Calculate(DataSet &dataSet)
{
Data=GetPointer(dataSet);
// Calculation
double adClosePrice[];
ArrayResize(adClosePrice,Data.Bars);
ArrayInitialize(adClosePrice,0);
for(int bar=1; barcloseTime)
adClosePrice[Data.Bars-1]=Data.Close[Data.Bars-1];
// Saving the components
ArrayResize(Component[0].Value,Data.Bars);
Component[0].CompName = "Closing price of the day";
Component[0].DataType = IndComponentType_ClosePrice;
Component[0].FirstBar = 2;
ArrayCopy(Component[0].Value,adClosePrice);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class MovingAvrg : public Indicator
{
public:
MovingAvrg(SlotTypes slotType)
{
SlotType=slotType;
IndicatorName="Moving Average";
WarningMessage = "";
IsAllowLTF = true;
ExecTime = ExecutionTime_DuringTheBar;
IsSeparateChart = false;
IsDiscreteValues = false;
IsDeafultGroupAll = false;
}
virtual void Calculate(DataSet &dataSet);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MovingAvrg::Calculate(DataSet &dataSet)
{
Data=GetPointer(dataSet);
// Reading the parameters
MAMethod maMethod =(MAMethod) ListParam[1].Index;
BasePrice basePrice=(BasePrice) ListParam[2].Index;
int period=(int) NumParam[0].Value;
int shift =(int) NumParam[1].Value;
int previous=CheckParam[0].Checked ? 1 : 0;
// TimeExecution
if(period==1 && shift==0)
{
if(basePrice == BasePrice_Open)
ExecTime = ExecutionTime_AtBarOpening;
else
if(basePrice==BasePrice_Close)
ExecTime = ExecutionTime_AtBarClosing;
}
else
ExecTime = ExecutionTime_DuringTheBar;
// Calculation
double basePrc[];
Price(basePrice,basePrc);
double movingAverage[];
MovingAverage(period,shift,maMethod,basePrc,movingAverage);
int firstBar=period+shift+1+previous;
// Saving the components
if(SlotType==SlotTypes_Open || SlotType==SlotTypes_Close)
{
ArrayResize(Component[1].Value, Data.Bars);
ArrayInitialize(Component[1].Value,0);
for(int bar=firstBar; bar Data.High[bar - 1] && value < Data.Open[bar]) || // The Data.Open price jumps above the indicator
(value1 < Data.Low[bar - 1] && value > Data.Open[bar]) || // The Data.Open price jumps below the indicator
(Data.Close[bar-1]value && value > Data.Open[bar])) // The Data.Open price is in a negative gap
tempVal=Data.Open[bar];
Component[1].Value[bar]=tempVal; // Entry or exit value
}
}
else
{
ArrayResize(Component[1].Value, Data.Bars);
ArrayResize(Component[2].Value, Data.Bars);
}
ArrayResize(Component[0].Value,Data.Bars);
Component[0].CompName = "MA Value";
Component[0].DataType = IndComponentType_IndicatorValue;
Component[0].FirstBar = firstBar;
ArrayCopy(Component[0].Value,movingAverage);
if(SlotType==SlotTypes_Open)
{
Component[1].CompName = "Position opening price";
Component[1].DataType = IndComponentType_OpenPrice;
}
if(SlotType==SlotTypes_OpenFilter)
{
Component[1].DataType = IndComponentType_AllowOpenLong;
Component[1].CompName = "Is long entry allowed";
Component[2].DataType = IndComponentType_AllowOpenShort;
Component[2].CompName = "Is short entry allowed";
}
if(SlotType==SlotTypes_Close)
{
Component[1].CompName = "Position closing price";
Component[1].DataType = IndComponentType_ClosePrice;
}
if(SlotType==SlotTypes_CloseFilter)
{
Component[1].DataType = IndComponentType_ForceCloseLong;
Component[1].CompName = "Close out long position";
Component[2].DataType = IndComponentType_ForceCloseShort;
Component[2].CompName = "Close out short position";
}
if(SlotType==SlotTypes_OpenFilter || SlotType==SlotTypes_CloseFilter)
{
if(ListParam[0].Text=="Moving Average rises")
IndicatorRisesLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
else
if(ListParam[0].Text=="Moving Average falls")
IndicatorFallsLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
else
if(ListParam[0].Text=="The bar opens above Moving Average")
BarOpensAboveIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
else
if(ListParam[0].Text=="The bar opens below Moving Average")
BarOpensBelowIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
else
if(ListParam[0].Text=="The bar opens above Moving Average after opening below it")
BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
else
if(ListParam[0].Text=="The bar opens below Moving Average after opening above it")
BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
else
if(ListParam[0].Text=="The position opens above Moving Average")
{
Component[0].PosPriceDependence=PositionPriceDependence_BuyHigherSellLower;
Component[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 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 Moving Average")
BarClosesBelowIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
else
if(ListParam[0].Text=="The bar closes above Moving Average")
BarClosesAboveIndicatorLogic(firstBar,previous,movingAverage,Component[1],Component[2]);
}
}
//+------------------------------------------------------------------+
//## Import Start
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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 == "Day Closing")
return new DayClosing(slotType);
if(indicatorName == "Moving Average")
return new MovingAvrg(slotType);
return NULL;
}
//+------------------------------------------------------------------+
//## Import Start
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class IndicatorSlot
{
public:
// Constructors
IndicatorSlot();
~IndicatorSlot();
// Properties
int SlotNumber;
SlotTypes SlotType;
string IndicatorName;
string LogicalGroup;
int SignalShift;
int SignalRepeat;
string IndicatorSymbol;
DataPeriod IndicatorPeriod;
Indicator *IndicatorPointer;
// Methods
bool GetUsePreviousBarValue();
string LogicalGroupToString();
string AdvancedParamsToString();
string GetIndicatorSymbol(string baseSymbol);
DataPeriod GetIndicatorPeriod(DataPeriod basePeriod);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
IndicatorSlot::IndicatorSlot()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
IndicatorSlot::~IndicatorSlot()
{
if(CheckPointer(IndicatorPointer)==POINTER_DYNAMIC)
delete IndicatorPointer;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IndicatorSlot::GetUsePreviousBarValue()
{
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)
group=Slot[slotNumber].IndicatorPointer.IsDeafultGroupAll ? "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
#include
//+------------------------------------------------------------------+
//| macros |
//+------------------------------------------------------------------+
#define EASYXML_START_OPEN "<"
#define EASYXML_START_CLOSE ">"
#define EASYXML_SELFCLOSE "/>"
#define EASYXML_CLOSE_OPEN ""
#define EASYXML_CLOSE_CLOSE ">"
#define EASYXML_WHITESPACE " \r\n\t"
#define EASYXML_LATIN "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
#define EASYXML_CDATA_OPEN ""
#define EASYXML_COMMENT_OPEN ""
#define EASYXML_PROLOG_OPEN ""
#define EASYXML_DOCTYPE_OPEN ""
#define EASYXML_ATTRIBUTE_SEPARATOR "="
#define EASYXML_ATTRIBUTE_COLON "\"'"
#define EASYXML_XMLFILE_ENDING ".xml"
#define HTTP_QUERY_CONTENT_LENGTH 5
#define EASYXML_ERR_CONNECTION_ATTEMPT 1
#define EASYXML_ERR_CONNECTION_OPEN 2
#define EASYXML_ERR_CONNECTION_URL 3
#define EASYXML_ERR_CONNECTION_FILEOPEN 4
#define EASYXML_ERR_CONNECTION_EMPTYSTREAM 5
#define EASYXML_INVALID_PROLOG 6
#define EASYXML_INVALID_COMMENT 7
#define EASYXML_INVALID_OPENTAG_START 8
#define EASYXML_INVALID_OPENTAG_CLOSE 9
#define EASYXML_INVALID_CLOSETAG 10
#define EASYXML_NO_CLOSETAG 11
#define EASYXML_INVALID_CDATA 12
#define EASYXML_INVALID_ATTRIBUTE 13
#define EASYXML_INVALID_FILENAME 14
#define EASYXML_INVALID_DOCTYPE 15
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CEasyXmlNode : public CObject
{
private:
CArrayObj *ChildNodes;
CArrayObj *AttributeNodes;
CEasyXmlNode *ParentNode;
string sName;
string sValue;
public:
void SetName(string pName);
void SetValue(string pValue);
void SetAttribute(string pName,string pValue);
string GetName(void);
string GetValue(void);
string GetAttribute(string pName);
CEasyXmlNode *CreateChild(CEasyXmlNode *pChildNode);
CEasyXmlNode *CreateSibling(CEasyXmlNode *pSiblingNode);
CEasyXmlNode *Parent(void);
void Parent(CEasyXmlNode *pParentNode);
CArrayObj *Children(void);
CArrayObj *Attributes(void);
CEasyXmlNode *LastChild(void);
CEasyXmlNode *FirstChild(void);
CEasyXmlNode();
~CEasyXmlNode();
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CEasyXmlNode::CEasyXmlNode()
{
ChildNodes=new CArrayObj;
AttributeNodes=new CArrayObj;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CEasyXmlNode::~CEasyXmlNode()
{
if(CheckPointer(ChildNodes) == POINTER_DYNAMIC)
{
for(int i = 0; i < ChildNodes.Total(); i++)
{
ChildNodes.Delete(i);
}
delete ChildNodes;
}
if(CheckPointer(AttributeNodes) == POINTER_DYNAMIC)
{
for(int i = 0; i < AttributeNodes.Total(); i++)
{
AttributeNodes.Delete(i);
}
delete AttributeNodes;
}
}
//+------------------------------------------------------------------+
//| set tag name |
//+------------------------------------------------------------------+
void CEasyXmlNode::SetName(string pName)
{
sName=pName;
}
//+------------------------------------------------------------------+
//| set tag content value |
//+------------------------------------------------------------------+
void CEasyXmlNode::SetValue(string pValue)
{
sValue=pValue;
}
//+------------------------------------------------------------------+
//| set attribute |
//+------------------------------------------------------------------+
void CEasyXmlNode::SetAttribute(string pName,string pValue)
{
CEasyXmlAttribute *Attribute=new CEasyXmlAttribute;
Attribute.SetName(pName);
Attribute.SetValue(pValue);
AttributeNodes.Add(Attribute);
}
//+------------------------------------------------------------------+
//| get attribute |
//+------------------------------------------------------------------+
string CEasyXmlNode::GetAttribute(string pName)
{
CEasyXmlAttribute *Attribute;
for(int i=0; i D:",IntegerToString(pLevel)," | P:",pPos);
SkipWhitespace(pText,pPos);
// Attributes
if(StringFind(EASYXML_LATIN,StringSubstr(pText,pPos,1))!=-1)
{
while(StringCompare(EASYXML_START_CLOSE,StringSubstr(pText, pPos, 1)) != 0 &&
StringCompare(EASYXML_SELFCLOSE, StringSubstr(pText, pPos, 2)) != 0 &&
!EndOfXml(pText,pPos))
{
sAttributes+=StringSubstr(pText,pPos,1);
pPos++;
}
blSuccess=ParseAttributes(pActualNode,sAttributes,sDebugSpace);
if(!blSuccess)
return(false);
}
// Self closing tag
if(StringCompare(EASYXML_SELFCLOSE,StringSubstr(pText,pPos,2))==0)
{
pPos+=2;
SkipWhitespace(pText,pPos);
// Detect if next sibling exists
blSibling=HasSiblings(pText,pPos);
continue;
}
// Start tag close
if(StringCompare(EASYXML_START_CLOSE,StringSubstr(pText,pPos,1))==0)
{
pPos++;
}
else
{
Err=EASYXML_INVALID_OPENTAG_CLOSE;
return(false);
}
// Skip comments
if(!SkipWhitespaceAndComments(pText,pPos,sDebugSpace))
return(false);
//---
// Parse next lower level tag and/or read text content
//---
// Next level tag
if(StringCompare(EASYXML_START_OPEN,StringSubstr(pText,pPos,1))==0 &&
StringCompare(EASYXML_CLOSE_OPEN,StringSubstr(pText,pPos,2))!=0 &&
StringCompare(EASYXML_CDATA_OPEN,StringSubstr(pText,pPos,StringLen(EASYXML_CDATA_OPEN)))!=0)
{
// Delve deeper
pActualNode=pActualNode.CreateChild(new CEasyXmlNode);
blSuccess=ParseRecursive(pActualNode,pText,pPos,pLevel+1);
if(!blSuccess)
return(false);
pActualNode=pActualNode.Parent();
}
// Read text content, even if it follows a closing tag
if(StringCompare(EASYXML_CDATA_OPEN,StringSubstr(pText,pPos,StringLen(EASYXML_CDATA_OPEN)))!=0)
{
// Tags in between text won't get parsed as XML nodes
while(StringCompare(EASYXML_CLOSE_OPEN+sTagName,StringSubstr(pText,pPos,StringLen(EASYXML_CLOSE_OPEN+sTagName)))!=0 &&
!EndOfXml(pText,pPos))
{
sTagContent+=StringSubstr(pText,pPos,1);
pPos++;
}
pActualNode.SetValue(sTagContent);
}
// Else read CDATA content, if there is any
else
{
int iClose=StringFind(pText,EASYXML_CDATA_CLOSE,pPos+StringLen(EASYXML_CDATA_OPEN));
if(iClose>0)
{
sTagContent = StringSubstr(pText, pPos + StringLen(EASYXML_CDATA_OPEN), (iClose - pPos - StringLen(EASYXML_CDATA_OPEN)));
pPos = iClose + StringLen(EASYXML_CDATA_CLOSE);
}
else
{
Err=EASYXML_INVALID_CDATA;
return(false);
}
pActualNode.SetValue(sTagContent);
}
// Debugging
if(blDebug && StringLen(sTagContent)!=0)
{
sDebugOutput=sTagContent;
StringTrimLeft(sDebugOutput);
sDebugOutput=(StringLen(sDebugOutput)>=50) ? StringSubstr(sDebugOutput,0,50)+"..." : sDebugOutput;
Print(sDebugSpace," ### Content ### "+sDebugOutput);
}
SkipWhitespace(pText,pPos);
//---
// Get end tag and compare it to start tag. return to upper level if valid
//---
if(StringFind(EASYXML_CLOSE_OPEN,StringSubstr(pText,pPos,2))==0)
{
pPos+=2;
}
else
{
Err=EASYXML_NO_CLOSETAG;
return(false);
}
//read end tag name
while(StringFind(EASYXML_CLOSE_CLOSE,StringSubstr(pText,pPos,1))==-1 && !EndOfXml(pText,pPos))
{
sCloseTagName+=StringSubstr(pText,pPos,1);
pPos++;
}
if(blDebug)
Print(sDebugSpace,"",sCloseTagName,"> D:",IntegerToString(pLevel)," | P:",pPos);
//compare start and end tag names
if(StringCompare(sCloseTagName,sTagName,false)==0)
{
pPos++;
}
else
{
Err=EASYXML_INVALID_CLOSETAG;
return(false);
}
// Skip comments
if(!SkipWhitespaceAndComments(pText,pPos,sDebugSpace))
return(false);
// Detect if next sibling exists
blSibling=HasSiblings(pText,pPos);
}
while(blSibling==true);
//return to upper level
return(true);
}
//+------------------------------------------------------------------+
//| pares attributes |
//+------------------------------------------------------------------+
bool CEasyXml::ParseAttributes(CEasyXmlNode *pActualNode,string pAttributes,string pDebugSpace)
{
int iAttrPos = 0;
int iValidAttrStart = 0;
int iValidAttrEnd = 0;
string sDebugOutput;
while(!EndOfXml(pAttributes,iAttrPos))
{
string sAttributeName;
string sAttributeValue;
string sAttributeValueColon;
// Some wellformed validity test
if(StringFind(EASYXML_LATIN,StringSubstr(pAttributes,iAttrPos,1))!=-1)
{
iValidAttrStart++;
}
// Read Attributename
while(StringCompare(EASYXML_ATTRIBUTE_SEPARATOR,StringSubstr(pAttributes,iAttrPos,1))!=0)
{
sAttributeName+=StringSubstr(pAttributes,iAttrPos,1);
iAttrPos++;
}
// Skip attribute separator
if(StringCompare(EASYXML_ATTRIBUTE_SEPARATOR,StringSubstr(pAttributes,iAttrPos,1))==0)
{
iAttrPos++;
}
// Read attribute value. Store Open Colon and use for further comparison
if(StringFind(EASYXML_ATTRIBUTE_COLON,StringSubstr(pAttributes,iAttrPos,1))!=-1)
{
sAttributeValueColon=StringSubstr(pAttributes,iAttrPos,1);
iAttrPos++;
}
while(StringFind(sAttributeValueColon,StringSubstr(pAttributes,iAttrPos,1))==-1)
{
sAttributeValue+=StringSubstr(pAttributes,iAttrPos,1);
iAttrPos++;
}
if(StringFind(sAttributeValueColon,StringSubstr(pAttributes,iAttrPos,1))!=-1)
{
iAttrPos++;
iValidAttrEnd++;
}
// If attribute is wellformed, set attribute to node
if(iValidAttrStart==iValidAttrEnd)
{
pActualNode.SetAttribute(sAttributeName,sAttributeValue);
}
else
{
Err=EASYXML_INVALID_ATTRIBUTE;
return(false);
}
// Debugging
if(blDebug)
{
sDebugOutput += (StringLen(sDebugOutput) != 0) ? " | " : "";
sDebugOutput += IntegerToString(iValidAttrEnd) + ": " + sAttributeName + " -> " + sAttributeValue;
}
SkipWhitespace(pAttributes,iAttrPos);
}
// Debugging
if(blDebug)
Print(pDebugSpace," ### Attributes ### ",sDebugOutput);
return(true);
}
//+------------------------------------------------------------------+
//| skip whitespace |
//+------------------------------------------------------------------+
void CEasyXml::SkipWhitespace(string &pText,int &pPos)
{
while(StringFind(EASYXML_WHITESPACE,StringSubstr(pText,pPos,1))!=-1)
{
pPos++;
}
}
//+------------------------------------------------------------------+
//| check if node has siblings |
//+------------------------------------------------------------------+
bool CEasyXml::HasSiblings(string &pText,int &pPos)
{
if(StringFind(EASYXML_START_OPEN,StringSubstr(pText,pPos,1))==0 &&
StringFind(EASYXML_CLOSE_OPEN,StringSubstr(pText,pPos,2))==-1)
{
return true;
}
else
{
return false;
}
}
//+------------------------------------------------------------------+
//| check for end of xml |
//+------------------------------------------------------------------+
bool CEasyXml::EndOfXml(string &pText,int &pPos)
{
return !(pPos0)
{
pPos=iClose+StringLen(EASYXML_PROLOG_CLOSE);
}
else
{
Err=EASYXML_INVALID_PROLOG;
return(false);
}
}
// Skip comments
if(!SkipWhitespaceAndComments(pText,pPos,""))
return(false);
// Skip doctype
if(StringCompare(EASYXML_DOCTYPE_OPEN,StringSubstr(pText,pPos,StringLen(EASYXML_DOCTYPE_OPEN)))==0)
{
int iClose=StringFind(pText,EASYXML_DOCTYPE_CLOSE,pPos+StringLen(EASYXML_DOCTYPE_OPEN));
if(blDebug)
Print("### DOCTYPE ### ",StringSubstr(pText,pPos,(iClose-pPos)+StringLen(EASYXML_DOCTYPE_CLOSE)));
if(iClose>0)
{
pPos=iClose+StringLen(EASYXML_DOCTYPE_CLOSE);
}
else
{
Err=EASYXML_INVALID_DOCTYPE;
return(false);
}
}
// Skip comments
if(!SkipWhitespaceAndComments(pText,pPos,""))
return(false);
return(true);
}
//+------------------------------------------------------------------+
//| skip xml comments |
//+------------------------------------------------------------------+
bool CEasyXml::SkipWhitespaceAndComments(string &pText,int &pPos,string pDebugSpace)
{
bool blNextComment=false;
// Do while there are consecutive comments
do
{
SkipWhitespace(pText,pPos);
if(StringCompare(EASYXML_COMMENT_OPEN,StringSubstr(pText,pPos,StringLen(EASYXML_COMMENT_OPEN)))==0)
{
int iClose=StringFind(pText,EASYXML_COMMENT_CLOSE,pPos+StringLen(EASYXML_COMMENT_OPEN));
if(blDebug)
Print(pDebugSpace," ### Comment ### ",StringSubstr(pText,pPos,(iClose-pPos)+StringLen(EASYXML_COMMENT_CLOSE)));
if(iClose>0)
{
pPos=iClose+StringLen(EASYXML_COMMENT_CLOSE);
}
else
{
Err=EASYXML_INVALID_COMMENT;
return(false);
}
}
SkipWhitespace(pText,pPos);
if(StringCompare(EASYXML_COMMENT_OPEN,StringSubstr(pText,pPos,StringLen(EASYXML_COMMENT_OPEN)))==0)
{
blNextComment=true;
}
else
{
blNextComment=false;
}
}
while(blNextComment==true);
return(true);
}
//+------------------------------------------------------------------+
//| error handling |
//+------------------------------------------------------------------+
bool CEasyXml::Error(int pPos=-1,bool pClear=true)
{
if(pClear)
Clear();
Print(EasyXmlError(Err,pPos));
return(false);
}
//+------------------------------------------------------------------+
//| get paresd document root |
//+------------------------------------------------------------------+
CEasyXmlNode *CEasyXml::GetDocumentRoot(void)
{
return DocumentRoot;
}
//+------------------------------------------------------------------+
//| return unparsed text |
//+------------------------------------------------------------------+
string CEasyXml::GetText(void)
{
return sText;
}
//+------------------------------------------------------------------+
//| Clear the doc tree |
//+------------------------------------------------------------------+
void CEasyXml::Clear(void)
{
StringInit(sText);
if(CheckPointer(DocumentRoot)==POINTER_DYNAMIC)
delete DocumentRoot;
DocumentRoot=new CEasyXmlNode;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CEasyXmlAttribute : public CObject
{
private:
string sName;
string sValue;
public:
void SetName(string pName);
void SetValue(string pValue);
string GetName(void);
string GetValue(void);
CEasyXmlAttribute();
~CEasyXmlAttribute();
};
//+------------------------------------------------------------------+
//| constructor |
//+------------------------------------------------------------------+
CEasyXmlAttribute::CEasyXmlAttribute()
{
}
//+------------------------------------------------------------------+
//| destructor |
//+------------------------------------------------------------------+
CEasyXmlAttribute::~CEasyXmlAttribute()
{
}
//+------------------------------------------------------------------+
//| set attribute name |
//+------------------------------------------------------------------+
void CEasyXmlAttribute::SetName(string pName)
{
sName=pName;
}
//+------------------------------------------------------------------+
//| set attribute value |
//+------------------------------------------------------------------+
void CEasyXmlAttribute::SetValue(string pValue)
{
sValue=pValue;
}
//+------------------------------------------------------------------+
//| get attribute name |
//+------------------------------------------------------------------+
string CEasyXmlAttribute::GetName(void)
{
return sName;
}
//+------------------------------------------------------------------+
//| get attribute value |
//+------------------------------------------------------------------+
string CEasyXmlAttribute::GetValue(void)
{
return sValue;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| returns trade server return code description |
//+------------------------------------------------------------------+
string EasyXmlError(int return_code,int pPos=-1)
{
string sErrorDescription;
switch(return_code)
{
case EASYXML_ERR_CONNECTION_ATTEMPT:
sErrorDescription = "Error in call of InternetAttemptConnect()";
break;
case EASYXML_ERR_CONNECTION_OPEN:
sErrorDescription = "Error in call of InternetOpenW()";
break;
case EASYXML_ERR_CONNECTION_URL:
sErrorDescription = "Error in call of InternetOpenUrlW()";
break;
case EASYXML_ERR_CONNECTION_FILEOPEN:
sErrorDescription = "Error in call of FileOpen()";
break;
case EASYXML_ERR_CONNECTION_EMPTYSTREAM:
sErrorDescription = "No return data from URL";
break;
case EASYXML_INVALID_PROLOG:
sErrorDescription = "Invalid Prologue";
break;
case EASYXML_INVALID_COMMENT:
sErrorDescription = "Invalid Comment";
break;
case EASYXML_INVALID_OPENTAG_START:
sErrorDescription = "Invalid Character found. Should be the beginning of an open tag";
break;
case EASYXML_INVALID_OPENTAG_CLOSE:
sErrorDescription = "Invalid Character found. Should be the close of an open tag";
break;
case EASYXML_INVALID_CLOSETAG:
sErrorDescription = "Invalid Close Tag. Tags must match!";
break;
case EASYXML_NO_CLOSETAG:
sErrorDescription = "No Close Tag found";
break;
case EASYXML_INVALID_CDATA:
sErrorDescription = "Invalid CDATA";
break;
case EASYXML_INVALID_ATTRIBUTE:
sErrorDescription = "Invalid Attribute";
break;
case EASYXML_INVALID_FILENAME:
sErrorDescription = "Invalid Cach File Name";
break;
case EASYXML_INVALID_DOCTYPE:
sErrorDescription = "Invalid Doctype";
break;
}
if(pPos!=-1)
{
sErrorDescription+=" P:"+IntegerToString(pPos);
}
return("*** "+sErrorDescription+" ***");
}
//+------------------------------------------------------------------+
//## Import Start
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class StrategyManager
{
SameDirSignalAction ParseSameDirSignalAction(string value);
OppositeDirSignalAction ParseOppositeDirSignalAction(string value);
public:
Strategy *ParseXmlStrategy(string xml);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
SameDirSignalAction StrategyManager::ParseSameDirSignalAction(string value)
{
if(value == "Add")
return SameDirSignalAction_Add;
if(value == "Loser")
return SameDirSignalAction_Loser;
if(value == "Winner")
return SameDirSignalAction_Winner;
return SameDirSignalAction_Nothing;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
OppositeDirSignalAction StrategyManager::ParseOppositeDirSignalAction(string value)
{
if(value == "Close")
return OppositeDirSignalAction_Close;
if(value == "Reduce")
return OppositeDirSignalAction_Reduce;
if(value == "Reverse")
return OppositeDirSignalAction_Reverse;
return OppositeDirSignalAction_Nothing;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Strategy *StrategyManager::ParseXmlStrategy(string xml)
{
IndicatorManager indicatorManager;
CEasyXml doc;
doc.SetDebugging(false);
bool isLoaded=doc.LoadXmlFromString(xml);
if(!isLoaded)
{
string message="Cannot parse the strategy XML file";
Comment(message);
Print(message);
return NULL;
}
CArrayObj *rootChildren=doc.GetDocumentRoot().Children();
int openFilters = 0;
int closeFilters = 0;
for(int i=0; i0)
m_FileHandle=handle;
else
Print("CreateFile: Error while creating log file!");
return (handle);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Logger::WriteLogLine(string text)
{
if(m_FileHandle <= 0)
return;
FileWrite(m_FileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text);
m_LogLines++;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Logger::WriteNewLogLine(string text)
{
if(m_FileHandle <= 0)
return;
FileWrite(m_FileHandle,"");
FileWrite(m_FileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),text);
m_LogLines+=2;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Logger::WriteLogRequest(string text,string request)
{
if(m_FileHandle <= 0)
return;
FileWrite(m_FileHandle,"\n"+text);
FileWrite(m_FileHandle,TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),request);
m_LogLines+=3;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Logger::FlushLogFile()
{
if(m_FileHandle <= 0)
return;
FileFlush(m_FileHandle);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Logger::CloseLogFile()
{
if(m_FileHandle <= 0)
return;
WriteNewLogLine(StringFormat("%s Closed.",MQLInfoString(MQL_PROGRAM_NAME)));
FileClose(m_FileHandle);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool Logger::IsLogLinesLimitReached(int maxLines)
{
return (m_LogLines>maxLines);
}
//+------------------------------------------------------------------+
//## Import Start
#define TRADE_RETRY_COUNT 4
#define TRADE_RETRY_WAIT 100
#define OP_FLAT -1
const double Epsilon=0.000001;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class ActionTrade5
{
// Fields
Strategy *m_Strategy;
DataSet *m_DataSet[];
DataMarket *m_DataMarket;
Logger *m_Logger;
// Aggregate position
int m_PositionTicket;
int m_PositionType;
datetime m_PositionTime;
double m_PositionLots;
double m_PositionOpenPrice;
double m_PositionStopLoss;
double m_PositionTakeProfit;
double m_PositionProfit;
double m_PositionCommission;
string m_PositionComment;
int m_ConsecutiveLosses;
// Properties
int m_LastError;
double m_PipsValue;
int m_PipsPoint;
int m_StopLevel;
datetime m_BarTime;
datetime m_TickTime;
datetime m_BarHighTime;
datetime m_BarLowTime;
double m_CurrentBarHigh;
double m_CurrentBarLow;
int m_TrailingStop;
TrailingStopMode m_TrailingMode;
int m_BreakEven;
int m_NBarExit;
int m_Digits;
StrategyPriceType m_OpenStrPriceType;
StrategyPriceType m_CloseStrPriceType;
ExecutionTime m_OpenTimeExec;
ExecutionTime m_CloseTimeExec;
bool m_UseLogicalGroups;
DictStringBool *m_GroupsAllowLong;
DictStringBool *m_GroupsAllowShort;
ListString *m_OpeningLogicGroups;
ListString *m_ClosingLogicGroups;
bool m_IsEnteredLong;
bool m_IsEnteredShort;
datetime m_TimeLastEntryBar;
datetime m_BarOpenTimeForLastCloseTick;
datetime m_BarOpenTimeForLastCloseEvent;
string m_DynamicInfoParams[];
string m_DynamicInfoValues[];
string m_DynamicInfoAccount[3];
// Methods
bool CheckEnvironment(int minimumBars);
bool CheckChartBarsCount(int minimumBars);
int FindBarsCountNeeded(void);
int SetAggregatePosition(void);
string AggregatePositionToString(void);
void AggregatePositionToNormalString(string &posinfo[]);
void UpdateDataSet(DataSet *dataSet,int maxBars);
void UpdateDataMarket(DataMarket *dataMarket);
bool IsTradeContextFree(void);
// Trading methods
bool ManageOrderSend(int type,double lots,double stoploss,double takeprofit);
bool CloseCurrentPosition();
bool ModifyPosition(double stoploss,double takeprofit);
double GetTakeProfitPrice(int type,double takeprofit);
double GetStopLossPrice(int type,double stoploss);
double CorrectTakeProfitPrice(int type,double takeprofit);
double CorrectStopLossPrice(int type,double stoploss);
double NormalizeEntrySize(double size);
double NormalizeEntryPrice(double price);
void SetMaxStopLoss(void);
void SetBreakEvenStop(void);
void SetTrailingStop(bool isNewBar);
void SetTrailingStopBarMode(void);
void SetTrailingStopTickMode(void);
void DetectSLTPActivation(void);
// Strategy Trader methods
TickType GetTickType(DataSet *dataSet,bool isNewBar);
void CalculateTrade(TickType ticktype);
PosDirection GetNewPositionDirection(OrderDirection ordDir,double ordLots,PosDirection posDir,double posLots);
TradeDirection AnalyzeEntryPrice(void);
TradeDirection AnalyzeEntryDirection(void);
void AnalyzeEntryLogicConditions(int bar,string group,double buyPrice,double sellPrice,bool &canOpenLong,bool &canOpenShort);
double AnalyzeEntrySize(OrderDirection ordDir,PosDirection &newPosDir);
TradeDirection AnalyzeExitPrice(void);
double TradingSize(double size);
double AccountPercentStopPoints(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);
double GetStopLossPoints(double lots);
double GetTakeProfitPoints(void);
void DoEntryTrade(TradeDirection tradeDir);
bool DoExitTrade(void);
bool IsWrongStopsExecution(void);
void ResendWrongStops(void);
void InitTrade(void);
public:
// Constructors
ActionTrade5(void);
~ActionTrade5(void);
// Properties
double Entry_Amount;
double Maximum_Amount;
double Adding_Amount;
double Reducing_Amount;
string Strategy_File_Name;
string Strategy_XML;
int Max_Data_Bars;
int Protection_Min_Account;
int Protection_Max_StopLoss;
bool Separate_SL_TP;
bool Write_Log_File;
bool FIFO_order;
int TrailingStop_Moving_Step;
int MaxLogLinesInFile;
int Bar_Close_Advance;
// Methods
int OnInit(void);
void OnTick(void);
void OnTrade(void);
void OnDeinit(const int reason);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ActionTrade5::ActionTrade5(void)
{
m_Logger = new Logger();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ActionTrade5::~ActionTrade5(void)
{
if(CheckPointer(m_Logger)==POINTER_DYNAMIC)
delete m_Logger;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int ActionTrade5::OnInit()
{
m_DataMarket = new DataMarket();
m_GroupsAllowLong = new DictStringBool();
m_GroupsAllowShort = new DictStringBool();
m_OpeningLogicGroups = new ListString();
m_ClosingLogicGroups = new ListString();
m_BarHighTime = 0;
m_BarLowTime = 0;
m_CurrentBarHigh = 0;
m_CurrentBarLow = 1000000;
m_Digits = Digits();
DataPeriod dataPeriod=(DataPeriod)Period();
string message=StringFormat("%s loaded.",MQLInfoString(MQL_PROGRAM_NAME));
Comment(message);
Print(message);
if(Write_Log_File)
{
m_Logger.CreateLogFile(m_Logger.GetLogFileName(_Symbol,_Period,5));
m_Logger.WriteLogLine(message);
m_Logger.WriteLogLine("Entry Amount: " +DoubleToString(Entry_Amount,2) +", "+
"Maximum Amount: " +DoubleToString(Maximum_Amount,2)+", "+
"Adding Amount: " +DoubleToString(Adding_Amount,2) +", "+
"Reducing Amount: "+DoubleToString(Reducing_Amount,2));
m_Logger.WriteLogLine("Protection Min Account: " +IntegerToString(Protection_Min_Account)+", "+
"Protection Max StopLoss: "+IntegerToString(Protection_Max_StopLoss));
m_Logger.WriteLogLine("Bar Close Advance: "+IntegerToString(Bar_Close_Advance));
m_Logger.FlushLogFile();
}
if(_Digits==2 || _Digits==3)
m_PipsValue=0.01;
else
if(_Digits==4 || _Digits==5)
m_PipsValue=0.0001;
else
m_PipsValue=_Digits;
if(_Digits==3 || _Digits==5)
m_PipsPoint=10;
else
m_PipsPoint=1;
m_StopLevel=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)+m_PipsPoint;
if(m_StopLevel<3*m_PipsPoint)
m_StopLevel=3*m_PipsPoint;
if(Protection_Max_StopLoss>0 && Protection_Max_StopLoss0 && AccountInfoDouble(ACCOUNT_EQUITY)Epsilon)
CloseCurrentPosition();
return;
}
// Checks and sets Max SL protection.
if(Protection_Max_StopLoss>0)
SetMaxStopLoss();
// Checks if position was closed.
DetectSLTPActivation();
if(m_BreakEven>0)
SetBreakEvenStop();
if(m_TrailingStop>0)
SetTrailingStop(isNewBar);
SetAggregatePosition();
if(isNewBar && Write_Log_File)
m_Logger.WriteNewLogLine(AggregatePositionToString());
if(m_DataSet[0].Bars >= m_Strategy.MinBarsRequired)
{
m_Strategy.CalculateStrategy(m_DataSet);
TickType tickType=GetTickType(m_DataSet[0],isNewBar);
CalculateTrade(tickType);
}
// Sends OrderModify on SL/TP errors
if(IsWrongStopsExecution())
ResendWrongStops();
AggregatePositionToNormalString(m_DynamicInfoAccount);
for(int i=0; i<3; i++)
{
string lblName="Lbl_pos_"+IntegerToString(i);
string val=m_DynamicInfoAccount[i]=="" ? "." : m_DynamicInfoAccount[i];
LabelTextChange(0,lblName,val);
}
m_Strategy.DynamicInfoSetValues(m_DynamicInfoValues);
int count= ArraySize(m_DynamicInfoValues);
for(int i=0; i=0; i--)
{
if((ticket=HistoryDealGetTicket(i))>0)
{
double price =HistoryDealGetDouble(ticket, DEAL_PRICE);
long time =HistoryDealGetInteger(ticket,DEAL_TIME);
string symbol=HistoryDealGetString(ticket, DEAL_SYMBOL);
double profit=HistoryDealGetDouble(ticket, DEAL_PROFIT);
if(price>Epsilon && time>0 && symbol==_Symbol)
{
if(profit<-Epsilon)
maxLosses++;
if(profit>Epsilon)
{
m_ConsecutiveLosses = maxLosses;
break;
}
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ActionTrade5::OnDeinit(const int reason)
{
if(Write_Log_File)
m_Logger.CloseLogFile();
if(CheckPointer(m_Strategy)==POINTER_DYNAMIC)
delete m_Strategy;
for(int i=0; i=barsNecessary;
if(isEnoughBars)
return(true);
string message="\n Cannot load enough bars! The expert needs minimum "+
IntegerToString(barsNecessary)+" bars."+
"\n Currently "+IntegerToString(bars)+" bars are loaded.";
if(MQLInfoInteger(MQL_TESTER))
message+="\n Please use a custom date period and set the dates properly.";
Comment(message);
Print(message);
return (false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int ActionTrade5::FindBarsCountNeeded()
{
int barStep=50;
int minBars=50;
int maxBars=3000;
// Initial state
int initialBars=MathMax(m_Strategy.MinBarsRequired,minBars);
initialBars=MathMax(m_Strategy.FirstBar,initialBars);
for(int i=0; i=initialBars+barStep/2
? roundedInitialBars
: roundedInitialBars+barStep;
for(int bars=firstTestBars; bars<=maxBars; bars+=barStep)
{
for(int i=0; iEpsilon)
{
// Reset the test if new tick has arrived.
for(int i=0; iEpsilon;
dataMarket.OldAsk = dataMarket.Ask;
dataMarket.OldBid = dataMarket.Bid;
dataMarket.OldClose = dataMarket.Close;
dataMarket.Ask = tick.ask;
dataMarket.Bid = tick.bid;
dataMarket.Close = Close(_Symbol,_Period,0);
dataMarket.Volume = Volume(_Symbol,_Period,0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int ActionTrade5::SetAggregatePosition()
{
m_PositionTicket = 0;
m_PositionType = OP_FLAT;
m_PositionTime = D'2050.01.01 00:00';
m_PositionLots = 0;
m_PositionOpenPrice = 0;
m_PositionStopLoss = 0;
m_PositionTakeProfit = 0;
m_PositionProfit = 0;
m_PositionCommission = 0;
m_PositionComment = "";
if(!PositionSelect(_Symbol))
return (0);
m_PositionTicket = (int) PositionGetInteger(POSITION_IDENTIFIER);
m_PositionType = (int) PositionGetInteger(POSITION_TYPE);
m_PositionTime = (datetime) MathMax(PositionGetInteger(POSITION_TIME),
PositionGetInteger(POSITION_TIME_UPDATE));
m_PositionOpenPrice = NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN),_Digits);
m_PositionLots = NormalizeDouble(PositionGetDouble(POSITION_VOLUME),2);
m_PositionProfit = NormalizeDouble(PositionGetDouble(POSITION_PROFIT)+
PositionGetDouble(POSITION_COMMISSION),2);
m_PositionCommission = NormalizeDouble(PositionGetDouble(POSITION_COMMISSION),2);
m_PositionStopLoss = NormalizeDouble(PositionGetDouble(POSITION_SL),_Digits);
m_PositionTakeProfit = NormalizeDouble(PositionGetDouble(POSITION_TP),_Digits);
m_PositionComment = PositionGetString(POSITION_COMMENT);
return (1);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string ActionTrade5::AggregatePositionToString()
{
if(m_PositionType==OP_FLAT)
return ("Position: Flat");
string text="Position: " +
"Ticket=" + IntegerToString(m_PositionTicket)+
", Time=" + TimeToString(m_PositionTime,TIME_SECONDS)+
", Type=" + (m_PositionType==OP_BUY ? "Long" : "Short")+
", Lots=" + DoubleToString(m_PositionLots,2)+
", Price=" + DoubleToString(m_PositionOpenPrice,_Digits)+
", StopLoss=" + DoubleToString(m_PositionStopLoss,_Digits)+
", TakeProfit=" + DoubleToString(m_PositionTakeProfit,_Digits)+
", Commission=" + DoubleToString(m_PositionCommission,2)+
", Profit=" + DoubleToString(m_PositionProfit,2);
if(m_PositionComment!="")
text=text+", \""+m_PositionComment+"\"";
return (text);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ActionTrade5::AggregatePositionToNormalString(string &posinfo[])
{
posinfo[0]=StringFormat("%s Balance: %.2f, Equity: %.2f",
TimeToString(m_TickTime,TIME_SECONDS),
AccountInfoDouble(ACCOUNT_BALANCE),
AccountInfoDouble(ACCOUNT_EQUITY));
if(m_PositionType==OP_FLAT)
{
posinfo[1] = "Position: Flat";
posinfo[2] = "";
}
else
{
string type=m_PositionType==OP_BUY ? "Long" : "Short";
posinfo[1]=StringFormat("Position: %s %.2f at %s, Profit %.2f",
type,m_PositionLots,
DoubleToString(m_PositionOpenPrice,_Digits),
m_PositionProfit);
posinfo[2]=StringFormat("Stop Loss: %s, Take Profit: %s",
DoubleToString(m_PositionStopLoss,_Digits),
DoubleToString(m_PositionTakeProfit,_Digits));
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool ActionTrade5::ManageOrderSend(int type,double lots,double stoploss,double takeprofit)
{
for(int attempt=0; attempt=_Point*breakeven)
{
if(m_PositionStopLoss0) ? lastErrorOrdClose : m_LastError;
}
}
}
else
if(m_PositionType==OP_SELL)
{
// Short position
double stopLossPrice=Low(_Symbol,_Period,1)+_Point*m_TrailingStop;
if(m_PositionStopLoss>stopLossPrice+m_PipsValue)
{
if(stopLossPrice>tick.ask)
{
if(stopLossPrice0) ? lastErrorOrdClose : m_LastError;
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ActionTrade5::SetTrailingStopTickMode()
{
MqlTick tick;
SymbolInfoTick(_Symbol,tick);
if(m_PositionType==OP_BUY)
{
// Long position
if(tick.bid>=m_PositionOpenPrice+m_TrailingStop*_Point)
if(m_PositionStopLoss30*1000)
{
Print("The waiting limit exceeded!");
return (false);
}
if(MQL5InfoInteger(MQL5_TRADE_ALLOWED))
return (true);
Sleep(100);
}
return (true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
TickType ActionTrade5::GetTickType(DataSet *dataSet,bool isNewBar)
{
DataPeriod period = dataSet.Period;
int bars = dataSet.Bars;
datetime serverTime = dataSet.ServerTime;
datetime barOpenTime = dataSet.Time[bars-1];
TickType type=TickType_Regular;
if(isNewBar)
{
m_BarOpenTimeForLastCloseTick=-1;
type=TickType_Open;
}
bool isClose=((barOpenTime+period*60)-serverTime)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 ActionTrade5::InitTrade()
{
m_OpenTimeExec=m_Strategy.Slot[0].IndicatorPointer.ExecTime;
m_OpenStrPriceType=StrategyPriceType_Unknown;
if(m_OpenTimeExec==ExecutionTime_AtBarOpening)
m_OpenStrPriceType=StrategyPriceType_Open;
else
if(m_OpenTimeExec==ExecutionTime_AtBarClosing)
m_OpenStrPriceType=StrategyPriceType_Close;
else
m_OpenStrPriceType=StrategyPriceType_Indicator;
m_CloseTimeExec=m_Strategy.Slot[m_Strategy.CloseSlotNumber()].IndicatorPointer.ExecTime;
m_CloseStrPriceType=StrategyPriceType_Unknown;
if(m_CloseTimeExec==ExecutionTime_AtBarOpening)
m_CloseStrPriceType=StrategyPriceType_Open;
else
if(m_CloseTimeExec==ExecutionTime_AtBarClosing)
m_CloseStrPriceType=StrategyPriceType_Close;
else
if(m_CloseTimeExec==ExecutionTime_CloseAndReverse)
m_CloseStrPriceType=StrategyPriceType_CloseAndReverse;
else
m_CloseStrPriceType=StrategyPriceType_Indicator;
m_UseLogicalGroups=m_Strategy.IsUsingLogicalGroups();
if(m_UseLogicalGroups)
{
m_Strategy.Slot[0].LogicalGroup="All";
m_Strategy.Slot[m_Strategy.CloseSlotNumber()].LogicalGroup="All";
for(int slot=0; slotoldPrice+Epsilon && buyPricebasePrice-Epsilon && buyPriceoldPrice+Epsilon && sellPricebasePrice-Epsilon && sellPrice=TimeDayOfWeek(m_TimeLastEntryBar) &&
m_DataSet[0].Time[bar] Epsilon;
bool canOpenShort = sellPrice > Epsilon;
if(m_UseLogicalGroups)
{
for(int i=0; i1 && key!="All") || m_GroupsAllowLong.Count()==1)
groupLongEntry=groupLongEntry || value;
}
bool groupShortEntry=false;
for(int i=0; i1 && key!="All") || m_GroupsAllowShort.Count()==1)
groupShortEntry=groupShortEntry || value;
}
canOpenLong = canOpenLong && groupLongEntry && m_GroupsAllowLong.Value("All");
canOpenShort = canOpenShort && groupShortEntry && m_GroupsAllowShort.Value("All");
}
else
{
AnalyzeEntryLogicConditions(bar,"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 ActionTrade5::AnalyzeEntryLogicConditions(int bar,string group,double buyPrice,
double sellPrice,bool &canOpenLong,bool &canOpenShort)
{
for(int slotIndex=0; slotIndex<=m_Strategy.CloseSlotNumber(); slotIndex++)
{
if(m_UseLogicalGroups && m_Strategy.Slot[slotIndex].LogicalGroup!=group &&
m_Strategy.Slot[slotIndex].LogicalGroup!="All")
continue;
for(int i=0; iindicatorValue+Epsilon;
break;
case PositionPriceDependence_PriceBuyLower:
canOpenLong=canOpenLong && buyPriceindicatorValue+Epsilon;
break;
case PositionPriceDependence_PriceSellLower:
canOpenShort=canOpenShort && sellPriceindicatorValue+Epsilon;
canOpenShort=canOpenShort && sellPriceindicatorValue+Epsilon;
break;
}
}
component=NULL;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double ActionTrade5::AnalyzeEntrySize(OrderDirection ordDir,PosDirection &newPosDir)
{
double size=0;
PosDirection posDir=m_DataMarket.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(m_DataMarket.PositionLots+TradingSize(m_Strategy.AddingLots) <
m_Strategy.MaxOpenLots+Epsilon)
{
switch(m_Strategy.SameSignalAction)
{
case SameDirSignalAction_Add:
size=TradingSize(m_Strategy.AddingLots);
break;
case SameDirSignalAction_Winner:
if(m_DataMarket.PositionProfit>Epsilon)
size=TradingSize(m_Strategy.AddingLots);
break;
case SameDirSignalAction_Loser:
if(m_DataMarket.PositionProfit<-Epsilon)
size=TradingSize(m_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(m_Strategy.OppSignalAction)
{
case OppositeDirSignalAction_Reduce:
if(m_DataMarket.PositionLots>TradingSize(m_Strategy.ReducingLots))
{
// Reducing
size=TradingSize(m_Strategy.ReducingLots);
newPosDir=posDir;
}
else
{
// Closing
size=m_DataMarket.PositionLots;
newPosDir=PosDirection_Closed;
}
break;
case OppositeDirSignalAction_Close:
size=m_DataMarket.PositionLots;
newPosDir=PosDirection_Closed;
break;
case OppositeDirSignalAction_Reverse:
size=m_DataMarket.PositionLots+TradingSize(m_Strategy.EntryLots);
newPosDir=(posDir==PosDirection_Long) ? PosDirection_Short : PosDirection_Long;
break;
case OppositeDirSignalAction_Nothing:
size=0;
newPosDir=posDir;
break;
}
}
}
else
{
// We are flat
size=TradingSize(m_Strategy.EntryLots);
if(m_Strategy.UseMartingale && m_DataMarket.ConsecutiveLosses>0)
{
double correctedAmount = size*MathPow(m_Strategy.MartingaleMultiplier, m_DataMarket.ConsecutiveLosses);
double normalizedAmount = NormalizeEntrySize(correctedAmount);
size = MathMax(normalizedAmount, SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN));
}
size=MathMin(size,m_Strategy.MaxOpenLots);
newPosDir=ordDir==OrderDirection_Buy ? PosDirection_Long : PosDirection_Short;
}
return (size);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
TradeDirection ActionTrade5::AnalyzeExitPrice()
{
IndicatorSlot *slot=m_Strategy.Slot[m_Strategy.CloseSlotNumber()];
int bar=m_DataSet[0].Bars-1;
// 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>m_DataMarket.OldBid+Epsilon && sellPricem_DataMarket.Bid-Epsilon && sellPricem_DataMarket.OldBid+Epsilon && buyPricem_DataMarket.Bid-Epsilon && buyPrice0 && (m_DataMarket.PositionOpenTime+(m_NBarExit*((int) m_DataSet[0].Period*60))0)
slotDirection=GetClosingDirection(slotDirection,m_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= m_Strategy.CloseSlotNumber()+1; slotEpsilon)
direction=GetClosingDirection(direction,m_Strategy.Slot[slot].IndicatorPointer.Component[c].DataType);
}
return (direction);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
TradeDirection ActionTrade5::ReduceDirectionStatus(TradeDirection baseDirection,TradeDirection direction)
{
if(baseDirection==direction || direction==TradeDirection_Both)
return (baseDirection);
if(baseDirection==TradeDirection_Both)
return (direction);
return (TradeDirection_None);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
TradeDirection ActionTrade5::IncreaseDirectionStatus(TradeDirection baseDirection,TradeDirection direction)
{
if(baseDirection==direction || direction==TradeDirection_None)
return (baseDirection);
if(baseDirection==TradeDirection_None)
return (direction);
return (TradeDirection_Both);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
TradeDirection ActionTrade5::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);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double ActionTrade5::GetStopLossPoints(double lots)
{
double indStop = DBL_MAX;
bool isIndStop = true;
int closeSlot=m_Strategy.CloseSlotNumber();
string name=m_Strategy.Slot[closeSlot].IndicatorName;
if(name=="Account Percent Stop")
indStop=AccountPercentStopPoints(m_Strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value,lots);
else
if(name=="ATR Stop")
indStop=m_Strategy.Slot[closeSlot].IndicatorPointer.Component[0].Value[m_DataSet[0].Bars-1]/m_DataSet[0].Point;
else
if(name=="Stop Loss" || name=="Stop Limit")
indStop=m_Strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value;
else
if(name=="Trailing Stop" || name=="Trailing Stop Limit")
indStop=m_Strategy.Slot[closeSlot].IndicatorPointer.NumParam[0].Value;
else
isIndStop=false;
double permStop = m_Strategy.UsePermanentSL ? m_Strategy.PermanentSL : DBL_MAX;
double stopLoss = 0;
if(isIndStop || m_Strategy.UsePermanentSL)
{
stopLoss=MathMin(indStop,permStop);
if(stopLoss=maxRetry)
{
m_DataMarket.WrongStopLoss =0;
m_DataMarket.WrongTakeProf =0;
m_DataMarket.WrongStopsRetry=0;
return (false);
}
bool isWrongStop=(m_DataMarket.WrongStopLoss>0 && m_DataMarket.PositionStopLoss0 && m_DataMarket.PositionTakeProfit0)
{
double stopLossPrice=0;
if(m_DataMarket.PositionDirection==PosDirection_Long)
stopLossPrice=m_DataMarket.Bid-stoploss*m_DataSet[0].Point;
else
if(m_DataMarket.PositionDirection==PosDirection_Short)
stopLossPrice=m_DataMarket.Ask+stoploss*m_DataSet[0].Point;
}
if(takeprofit>0)
{
double takeProfitPrice=0;
if(m_DataMarket.PositionDirection==PosDirection_Long)
takeProfitPrice=m_DataMarket.Bid+takeprofit*m_DataSet[0].Point;
else
if(m_DataMarket.PositionDirection==PosDirection_Short)
takeProfitPrice=m_DataMarket.Ask-takeprofit*m_DataSet[0].Point;
}
bool responseOk=ModifyPosition(stoploss,takeprofit);
if(responseOk)
{
m_DataMarket.WrongStopLoss = 0;
m_DataMarket.WrongTakeProf = 0;
m_DataMarket.WrongStopsRetry = 0;
}
else
m_DataMarket.WrongStopsRetry++;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double ActionTrade5::TradingSize(double size)
{
if(m_Strategy.UseAccountPercentEntry)
size=(size/100)*m_DataMarket.AccountEquity/m_DataSet[0].MarginRequired;
return NormalizeEntrySize(size);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double ActionTrade5::AccountPercentStopPoints(double percent,double lots)
{
double balance = m_DataMarket.AccountBalance;
double moneyrisk = balance*percent/100;
double spread = m_DataSet[0].Spread;
double tickvalue = m_DataSet[0].TickValue;
double stoploss = moneyrisk/(lots*tickvalue) - spread;
return (stoploss);
}
// The Forex Strategy Builder Expert
ActionTrade5* actionsTrade;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnInit()
{
actionsTrade = new ActionTrade5();
actionsTrade.Entry_Amount = (Entry_Amount >77700)?0.1:Entry_Amount;
actionsTrade.Maximum_Amount = (Maximum_Amount >77700)?0.1:Maximum_Amount;
actionsTrade.Adding_Amount = (Adding_Amount >77700)?0.1:Adding_Amount;
actionsTrade.Reducing_Amount = (Reducing_Amount>77700)?0.1:Reducing_Amount;
actionsTrade.Strategy_File_Name = Strategy_File_Name;
actionsTrade.Strategy_XML = Strategy_XML;
actionsTrade.Max_Data_Bars = Max_Data_Bars;
actionsTrade.Protection_Min_Account = Protection_Min_Account;
actionsTrade.Protection_Max_StopLoss = Protection_Max_StopLoss;
actionsTrade.Separate_SL_TP = Separate_SL_TP;
actionsTrade.Write_Log_File = Write_Log_File;
actionsTrade.TrailingStop_Moving_Step = TrailingStop_Moving_Step;
actionsTrade.FIFO_order = FIFO_order;
actionsTrade.MaxLogLinesInFile = MaxLogLinesInFile;
actionsTrade.Bar_Close_Advance = Bar_Close_Advance;
int result=actionsTrade.OnInit();
if(result==INIT_SUCCEEDED)
actionsTrade.OnTick();
return (result);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTick()
{
if(__symbol!=_Symbol || __period!=_Period)
{
if(__period > 0)
{
actionsTrade.OnDeinit(-1);
actionsTrade.OnInit();
}
__symbol=_Symbol;
__period=_Period;
}
actionsTrade.OnTick();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTrade()
{
actionsTrade.OnTrade();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
actionsTrade.OnDeinit(reason);
if(CheckPointer(actionsTrade)==POINTER_DYNAMIC)
delete actionsTrade;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+