212 lines
8.9 KiB
MQL5
212 lines
8.9 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| base.mqh |
|
|
//| Benjamin Pillet |
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Benjamin Pillet"
|
|
#property link ""
|
|
|
|
#include <Trade\Trade.mqh>
|
|
CTrade trade;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| global variables |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//--- main input parameters
|
|
input ulong MagicNumber = 1234;
|
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_D1;
|
|
input int AddPoint = 50;
|
|
input double TpSlRatio = 2; //take profit/stop loss ratio
|
|
input double SlPercent = 2;
|
|
input bool SafeMode = false;//safe mode on
|
|
input double SafeActivationRatio = 4;
|
|
input double SafeSlRatio = 2;
|
|
input bool TrailingMode =false;//trailing mode on
|
|
input double TrailingActivationRatio = 6;
|
|
input double TrailingDistance = 20; //trailing distance
|
|
input bool CancelOrderOnTP = true; //cancel orders on TP
|
|
input bool CancelOrderOnSL = true; //cancel orders on profitable SL
|
|
input bool CancelOrderOnLoss = false; //cancel orders on non-profitable SL
|
|
input bool OrderOnce = false; //place orders only once
|
|
input bool DrawLines = true; //Draw safe and trailing activation lines
|
|
input int TimeOffset = 0;
|
|
|
|
//--- market variables
|
|
double volumeStep;
|
|
double tickSize;
|
|
double tickPrice;
|
|
double bid;
|
|
double prevBid;
|
|
double prevAsk;
|
|
double ask;
|
|
long tickVolume[];
|
|
MqlRates bar[];
|
|
double lastOpen;
|
|
|
|
//--- time variables
|
|
MqlDateTime firstBar;
|
|
MqlDateTime today;
|
|
MqlDateTime startTime[];
|
|
MqlDateTime endTime[];
|
|
datetime lastRefreshDay;
|
|
datetime prevDay;
|
|
|
|
//--- account variables
|
|
double accountBalance;
|
|
double accountEquity;
|
|
|
|
//--- trade variables
|
|
|
|
//--- orders and positions handling system variables
|
|
bool orderConditions;
|
|
bool resetOrderPlaced;
|
|
bool orderPlaced[2];
|
|
int arrayIndex;
|
|
int arraySize;
|
|
double cancellingSL[2];
|
|
int prevPositionTotal;
|
|
int positionTotal;
|
|
ulong positionTicket[];
|
|
double safeActivationPrice[];
|
|
double safeSL[];
|
|
double trailingActivationPrice[];
|
|
double trailingDistance[];
|
|
double trailingSL;
|
|
long positionType;
|
|
double positionOpenPrice;
|
|
double positionCurrentPrice;
|
|
double positionTP;
|
|
double positionSL;
|
|
ulong lastPositionTicket;
|
|
ulong posTicket;
|
|
ulong histOrderTicket;
|
|
ulong histDealTicket;
|
|
double histOrderPrice;
|
|
double initialPositionSL;
|
|
bool profitableSL;
|
|
bool timeSet;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| functions |
|
|
//+------------------------------------------------------------------+
|
|
|
|
double NormalisePrice(double p){
|
|
return (MathRound(p/tickSize)*tickSize);
|
|
}
|
|
|
|
double LotsCalculator(double openPrice, double closePrice, double balance){
|
|
double lots = NormalizeDouble(((balance*(SlPercent/100))/(MathAbs(openPrice-closePrice)*(tickPrice/tickSize)))/volumeStep,0)*volumeStep;
|
|
if(lots < SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)){
|
|
lots = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
|
|
}
|
|
else if(lots > SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX)){
|
|
lots = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
|
|
}
|
|
return lots;
|
|
}
|
|
|
|
void setVariables(){
|
|
lastOpen = 0;
|
|
volumeStep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
|
|
tickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
|
|
tickPrice = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
|
|
}
|
|
|
|
void refreshVariables(){
|
|
bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
|
|
ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
|
|
accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
accountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
|
|
ArraySetAsSeries(bar,true);
|
|
CopyRates(_Symbol,TimeFrame,0,3,bar);
|
|
TimeToStruct(bar[1].time,firstBar);
|
|
TimeToStruct(TimeCurrent(),today);
|
|
//refresh once a day
|
|
if(today.day != lastRefreshDay){
|
|
volumeStep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
|
|
tickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
|
|
tickPrice = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
|
|
lastRefreshDay = today.day;
|
|
}
|
|
}
|
|
|
|
void AddPosition(){ //add a position into the safe and trailing system. The position has to be previously selected and checked
|
|
arrayIndex = arraySize;
|
|
arraySize = arraySize + 1;
|
|
ArrayResize(positionTicket,arraySize,10);
|
|
positionTicket[arrayIndex] = PositionGetInteger(POSITION_TICKET);
|
|
positionType = PositionGetInteger(POSITION_TYPE);
|
|
positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
positionSL = PositionGetDouble(POSITION_SL);
|
|
//check if the SL is already in a safe/profitable place
|
|
if((positionType == POSITION_TYPE_BUY && positionSL < positionOpenPrice) || (positionType==POSITION_TYPE_SELL && positionSL > positionOpenPrice)){
|
|
initialPositionSL = positionSL; //if not profitable SL then the current SL is the initial SL of the position
|
|
profitableSL = false;
|
|
}
|
|
else{
|
|
profitableSL = true;
|
|
if(TrailingMode){
|
|
HistorySelect(0,TimeCurrent());
|
|
for(int j=HistoryOrdersTotal()-1; j>=0; j--){
|
|
histOrderTicket = HistoryOrderGetTicket(j);
|
|
if(HistoryOrderGetInteger(histOrderTicket,ORDER_POSITION_ID) == PositionGetInteger(POSITION_IDENTIFIER)){
|
|
initialPositionSL = HistoryOrderGetDouble(histOrderTicket,ORDER_SL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(SafeMode && !profitableSL){
|
|
ArrayResize(safeActivationPrice,arraySize,10);
|
|
ArrayResize(safeSL,arraySize,10);
|
|
if(positionType == POSITION_TYPE_BUY){
|
|
safeActivationPrice[arrayIndex] = positionOpenPrice + (positionOpenPrice-positionSL)*SafeActivationRatio;
|
|
safeSL[arrayIndex] = NormalisePrice(positionOpenPrice + (positionOpenPrice-positionSL)*SafeSlRatio);
|
|
if(safeSL[arrayIndex]<0)safeSL[arrayIndex] = 0;
|
|
}
|
|
else if(positionType==POSITION_TYPE_SELL){
|
|
safeActivationPrice[arrayIndex] = positionOpenPrice - (positionSL-positionOpenPrice)*SafeActivationRatio;
|
|
safeSL[arrayIndex] = NormalisePrice(positionOpenPrice - (positionSL-positionOpenPrice)*SafeSlRatio);
|
|
if(safeSL[arrayIndex]<0)safeSL[arrayIndex] = 0;
|
|
}
|
|
if(DrawLines){
|
|
ObjectCreate(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJ_HLINE,0,0,safeActivationPrice[arrayIndex]);
|
|
ObjectSetInteger(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_COLOR,clrDodgerBlue);
|
|
ObjectSetInteger(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_STYLE,STYLE_DASH);
|
|
}
|
|
}
|
|
if(TrailingMode){
|
|
ArrayResize(trailingActivationPrice,arraySize,10);
|
|
ArrayResize(trailingDistance,arraySize,10);
|
|
if(positionType == POSITION_TYPE_BUY){
|
|
trailingActivationPrice[arrayIndex] = positionOpenPrice + (positionOpenPrice-initialPositionSL)*TrailingActivationRatio;
|
|
trailingDistance[arrayIndex] = (trailingActivationPrice[arrayIndex]-positionOpenPrice)*(TrailingDistance/100);
|
|
}
|
|
else if(positionType==POSITION_TYPE_SELL){
|
|
trailingActivationPrice[arrayIndex] = positionOpenPrice - (initialPositionSL-positionOpenPrice)*TrailingActivationRatio;
|
|
trailingDistance[arrayIndex] = (positionOpenPrice - trailingActivationPrice[arrayIndex])*(TrailingDistance/100);
|
|
}
|
|
if(DrawLines){
|
|
ObjectCreate(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJ_HLINE,0,0,trailingActivationPrice[arrayIndex]);
|
|
ObjectSetInteger(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_COLOR,clrMediumOrchid);
|
|
ObjectSetInteger(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_STYLE,STYLE_DASH);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CloseAllLongPositions(){
|
|
for(int i=0; i< PositionsTotal(); i++){
|
|
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) trade.PositionClose(PositionGetTicket(i));
|
|
}
|
|
}
|
|
void CloseAllShortPositions(){
|
|
for(int i=0; i< PositionsTotal(); i++){
|
|
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) trade.PositionClose(PositionGetTicket(i));
|
|
}
|
|
}
|
|
void CloseAllPositions(){
|
|
for(int i=0; i< PositionsTotal(); i++){
|
|
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol) trade.PositionClose(PositionGetTicket(i));
|
|
}
|
|
}
|
|
|