635 lines
55 KiB
MQL5
635 lines
55 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| TopoBeta.mq5 |
|
|
//| Copyright 2021, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2021, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
|
|
#include <Trade\Trade.mqh>
|
|
#include <Trade\HistoryOrderInfo.mqh>
|
|
#include <Trade\SymbolInfo.mqh>
|
|
#include <Trade\PositionInfo.mqh>
|
|
#include <Trade\AccountInfo.mqh>
|
|
#include <MovingAverages.mqh>
|
|
|
|
#include "..\\utils\\Utils.mqh"
|
|
#include "..\\utils\\ChartUtils.mqh"
|
|
#include "..\\models\\PositionInfo.mqh"
|
|
#include "..\\models\\HistoryPositionInfo.mqh"
|
|
#include "..\\models\\RiskInfo.mqh"
|
|
|
|
CTrade trade;
|
|
Utils utils;
|
|
ChartUtils chartUtils;
|
|
|
|
//utils
|
|
#define TOPO_MAGIC 47829674
|
|
enum IntervalsToAmplitude {all = 0, id5 = 5, id10 = 10, id30 = 30, id50 = 50, id70 = 70, id100 = 100, id120 = 120, id150 = 150, id240 = 240, id500 = 500, id1440 = 1440}; // select Predefined intervals with good results
|
|
enum ModeEnv {dev = 0, test = 1, prod = 2};
|
|
//input
|
|
input group "--- Generals ---"
|
|
input ModeEnv modeEnv = 0; // env mode
|
|
input IntervalsToAmplitude temporalToAmplitude = 0; // temporals to analize the amplitude
|
|
input group "--- Risk ---"
|
|
input double MaxRiskByTradeInPercent = 1; // Max Risk by trade in percentage
|
|
input double MaxDrawdownInPercent = 10; // Max Risk by day in percentage
|
|
input int numberConsecutiveLossToStop = 40; // number of the consecutive loss to stop
|
|
input int timeInMinuteToStopConsecutiveLoss = 5; // time in minutes to stop after consecutive loss
|
|
input bool useDisableRisk = false; // disable drawdown and consecutive loss risk
|
|
input group "--- lotage, positions, takeprofit and stoploss ---"
|
|
input bool useMoveStoploss = true; // use movement of stoploss
|
|
input bool usePartialClose = false; // use partial close
|
|
input bool useMinLotInTradeIfNotEnough = true; // use min lot in a trade if not enough to operate
|
|
input bool useFixedLotage = false; // use fixed lotage(0.01)
|
|
input bool useFixedStopLoss = true; // use fixed stopLoss 0.5%
|
|
input bool useFixedTakeProfit = true; // use fixed takeProfit = amplitude
|
|
input double numberPeriodsToClosePosition = 20; // number of periods to close positions
|
|
input group "--- confirmations ---"
|
|
input double spreadUmbral = 10;
|
|
input bool useMacDConfirm = true; // use macd to confirm
|
|
input int SIGNAL=9; // macd signal for each period
|
|
input bool useRegressionConfirm = false; // use regression confirm
|
|
input double macdUmbral = 70; // macd umbral, (lastHistBar - penultimeHistBar) > macdUmbral
|
|
input group "--- TODO confirmations, please do not change them ---"
|
|
input int numberToDivPeriod = 0;
|
|
input int consecutiveCandleToConfirmInPercentUmbral = 4;
|
|
input group "--- to try period and amplitude umbrals in test mode ---"
|
|
input int periodSelected = 5; // period in bars to analize the amplitude (only in test mode)
|
|
input double amplitudeValues = 2; // umbral values to analize the amplitude (only in test mode))
|
|
//consts
|
|
const int positionsInfoLength = 1500;
|
|
const int tradeDeviation = 10;
|
|
//amplitude data
|
|
int periodInBars[];
|
|
double amplitudeUmbrals[];
|
|
//trade info
|
|
PositionInfo positionsInfo[];
|
|
HistoryPositionInfo historyPositionsInfo[];
|
|
int periodInBarsLength;
|
|
//init time
|
|
datetime initTime;
|
|
//risk info
|
|
RiskInfo riskInfo;
|
|
//indicators handles
|
|
int MACDhadlingBuffer[];
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit() {
|
|
//--- initialize common information
|
|
trade.SetExpertMagicNumber(TOPO_MAGIC); // magic
|
|
trade.SetMarginMode();
|
|
trade.SetTypeFillingBySymbol(Symbol());
|
|
chartUtils.setChartTemplate();
|
|
//initTime
|
|
initTime = TimeCurrent();
|
|
//init periodInBars and amplitudeUmbrals
|
|
setTemporalsAmplitudes();
|
|
periodInBarsLength = ArraySize(periodInBars);
|
|
//init risk info
|
|
double moneyAllowToLoss = NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE)*(MaxDrawdownInPercent/100),_Digits);
|
|
riskInfo = initRiskInfo(MaxRiskByTradeInPercent, MaxDrawdownInPercent, initTime,moneyAllowToLoss,numberConsecutiveLossToStop,timeInMinuteToStopConsecutiveLoss);
|
|
//initial positionInfo with default values
|
|
ArrayResize(positionsInfo,positionsInfoLength);
|
|
ArrayResize(historyPositionsInfo,positionsInfoLength);
|
|
ArrayResize(MACDhadlingBuffer,positionsInfoLength);
|
|
for(int i = 0; i < positionsInfoLength; i++) {
|
|
positionsInfo[i] = createEmptyPosition(initTime);
|
|
historyPositionsInfo[i] = createEmptyHistoryPosition(initTime);
|
|
}
|
|
//restrictions
|
|
if(!useDisableRisk && useFixedLotage) {
|
|
Print("we need calculate better the riskInMoney when the lotage is a value fixed");
|
|
return -10;
|
|
}
|
|
TesterHideIndicators(true);
|
|
for(int i=0; i<periodInBarsLength && !IsStopped(); i++) {
|
|
int bars = periodInBars[i];
|
|
int MACDhadling=iMACD(NULL,0,1,bars,SIGNAL,PRICE_CLOSE);
|
|
MACDhadlingBuffer[i] = MACDhadling;
|
|
if(MACDhadling == INVALID_HANDLE) {
|
|
Print("Macd error inicialization, Code = ",GetLastError());
|
|
return -1;
|
|
}
|
|
}
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason) {
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick() {
|
|
// check if close positions by expiration
|
|
checkIfClosePositionByExpiration();
|
|
//check if we can move stoploss
|
|
if(useMoveStoploss) {
|
|
tryMoveStopLoss();
|
|
}
|
|
//check if we can make partial close
|
|
if(usePartialClose) {
|
|
tryPartialClose();
|
|
}
|
|
if(!utils.checkIfNewBar())
|
|
return;
|
|
//try open positions
|
|
int positionPendingToMakeTrade = openPositions();
|
|
//there position opened
|
|
if(positionPendingToMakeTrade == 0)
|
|
return;
|
|
// make trade in position opened
|
|
for(int i=0; i<periodInBarsLength && !IsStopped(); i++) {
|
|
int bars = periodInBars[i];
|
|
bool canMakeTrade = canMakeTradeFromRiskInfo(riskInfo, periodInBars, positionsInfo, periodInBarsLength, initTime);
|
|
if(useDisableRisk || (!useDisableRisk && canMakeTrade)) {
|
|
MakeTrade(bars);
|
|
} else {
|
|
positionsInfo[bars] = createEmptyPosition(initTime);
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void OnTrade() {
|
|
// update position info
|
|
updatePositionInfo();
|
|
//update risk info
|
|
updateRiskInfo(riskInfo,TOPO_MAGIC);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void updatePositionInfo () {
|
|
for(int i=0; i<periodInBarsLength && !IsStopped(); i++) {
|
|
int index = periodInBars[i];
|
|
PositionInfo currentPositionInfo = positionsInfo[index];
|
|
bool active = PositionSelectByTicket(currentPositionInfo.ticket);
|
|
if(!active) {
|
|
MqlRates rates[];
|
|
if(CopyRates(Symbol(),Period(),0, 1,rates)==-1) {
|
|
Print("CopyRates error de copia, Code = ",GetLastError());
|
|
return;
|
|
}
|
|
positionsInfo[index] = createEmptyPosition(initTime);
|
|
historyPositionsInfo[index] = createHistoryPositionInfo(currentPositionInfo.position,rates[0].open,TimeCurrent(),currentPositionInfo.openPositionTime,currentPositionInfo.signal);
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void tryMoveStopLoss() {
|
|
int total = PositionsTotal();
|
|
for(int i=0; i<total && !IsStopped(); i++) {
|
|
ulong ticket = PositionGetTicket(i);
|
|
bool selected = PositionSelectByTicket(ticket);
|
|
if(!selected)
|
|
continue;
|
|
if(PositionGetDouble(POSITION_PROFIT) < 0)
|
|
continue;
|
|
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
|
|
double tp = PositionGetDouble(POSITION_TP);
|
|
double sl = PositionGetDouble(POSITION_SL);
|
|
bool isLong = currentPrice > sl;
|
|
double currentAmplitudeFromSl = utils.absDiffInPercent(sl,currentPrice);
|
|
double displacement = sl * (1/100);
|
|
if(currentAmplitudeFromSl < 0.5)
|
|
continue;
|
|
if(currentAmplitudeFromSl < 1.5)
|
|
displacement = sl * (0.3/100);
|
|
double newStopLossLevel = isLong ? (sl + displacement) : (sl - displacement);
|
|
bool moved = trade.PositionModify(ticket,newStopLossLevel,tp);
|
|
ulong code = trade.ResultRetcode();
|
|
string msj = "";
|
|
if(moved && code == TRADE_RETCODE_DONE) {
|
|
msj = StringFormat("moved SL: ticket:(%d) ,openPrice:(%f) ,Sl:(%f) ,newSL:(%f)", ticket, openPrice, sl, newStopLossLevel);
|
|
} else {
|
|
msj = StringFormat("ERROR code(%d): in move SL with: ticket:(%d) ,openPrice:(%f) ,Sl:(%f) ,newSL:(%f)", code, ticket, openPrice, sl, newStopLossLevel);
|
|
}
|
|
Print(msj);
|
|
Alert(msj);
|
|
for(int j=0; j<periodInBarsLength && !IsStopped(); j++) {
|
|
int bars = periodInBars[j];
|
|
PositionInfo curr = positionsInfo[bars];
|
|
if(curr.ticket == ticket) {
|
|
curr.stopLossLevel = newStopLossLevel;
|
|
positionsInfo[bars] = curr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void tryPartialClose() {
|
|
int total = PositionsTotal();
|
|
for(int i=0; i<total && !IsStopped(); i++) {
|
|
ulong ticket = PositionGetTicket(i);
|
|
bool selected = PositionSelectByTicket(ticket);
|
|
if(!selected)
|
|
continue;
|
|
if(PositionGetInteger(POSITION_TIME) != PositionGetInteger(POSITION_TIME_UPDATE))
|
|
continue;
|
|
double profit = PositionGetDouble(POSITION_PROFIT);
|
|
if(PositionGetDouble(POSITION_PROFIT) < 0)
|
|
continue;
|
|
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
|
|
double tp = PositionGetDouble(POSITION_TP);
|
|
double currentAmplitude = utils.absDiffInPercent(openPrice,currentPrice);
|
|
double tpAmplitude = utils.absDiffInPercent(openPrice,tp);
|
|
double amplitudeUmbral = tpAmplitude / 2;
|
|
if(currentAmplitude < amplitudeUmbral)
|
|
continue;
|
|
double v = PositionGetDouble(POSITION_VOLUME);
|
|
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
|
|
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
|
|
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
|
|
if(v > minLot) {
|
|
double newVToClose = v / 4;
|
|
newVToClose = NormalizeDouble(NormalizeDouble(newVToClose/lotStep,_Digits)*lotStep, 2);
|
|
if(newVToClose < minLot)
|
|
newVToClose = minLot;
|
|
if(newVToClose > maxLot )
|
|
newVToClose = maxLot;
|
|
trade.PositionClosePartial(ticket,newVToClose,tradeDeviation);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int openPositions() {
|
|
ResetLastError();
|
|
int cantPositionsOpen = 0;
|
|
datetime timeCurrent = TimeCurrent();
|
|
for(int i=0; i<periodInBarsLength && !IsStopped(); i++) {
|
|
int bars = periodInBars[i];
|
|
bool exitPosition = exitPositionByPeriodInBars(positionsInfo, bars);
|
|
if(exitPosition)
|
|
continue;
|
|
int operation = 0;
|
|
MqlRates rates[];
|
|
int ratesPos = 0;
|
|
if(CopyRates(Symbol(),Period(),ratesPos, bars + 2,rates)==-1) {
|
|
Print("CopyRates error de copia, Code = ",GetLastError());
|
|
return cantPositionsOpen;
|
|
}
|
|
if(ArraySize(rates) <= bars) {
|
|
return cantPositionsOpen; // only pass when we analize all the historial
|
|
}
|
|
ArraySetAsSeries(rates, true);
|
|
|
|
datetime timeCloseInPassed = rates[bars + 1].time;
|
|
ulong timePassed = rates[1].time - timeCloseInPassed;
|
|
if(modeEnv == 0 && modeEnv == 1) {
|
|
ulong timeRequeredToPass = bars * 60;
|
|
// check of there empty data in the history
|
|
if(timePassed != timeRequeredToPass)
|
|
continue;
|
|
}
|
|
double lastClose = rates[1].close; // last bar completed
|
|
double closeInPassed = rates[bars + 1].close;
|
|
double amplitude = utils.absDiffInPercent(closeInPassed, lastClose);
|
|
if(amplitude <= amplitudeUmbrals[i])
|
|
continue;
|
|
if(closeInPassed < lastClose) {
|
|
operation = -1;
|
|
}
|
|
if(closeInPassed > lastClose) {
|
|
operation = 1;
|
|
}
|
|
//int stopK = bars < 20 ? 1 : bars - 20;
|
|
//int index = 0;
|
|
//for(int k = bars; k > stopK; k--) {
|
|
// lastClose = rates[1].close; // last bar completed
|
|
// closeInPassed = rates[k + 1].close;
|
|
// amplitude = utils.absDiffInPercent(closeInPassed, lastClose);
|
|
// if(amplitude <= amplitudeUmbrals[i])
|
|
// continue;
|
|
// index = k;
|
|
// if(closeInPassed < lastClose) {
|
|
// operation = -1;
|
|
// break;
|
|
// }
|
|
// if(closeInPassed > lastClose) {
|
|
// operation = 1;
|
|
// break;
|
|
// }
|
|
//}
|
|
// confirm segment
|
|
// passed oportunity confirm ins small period
|
|
if(useRegressionConfirm) {
|
|
double umBuffer [6] = {0.8, 1, 3, 3, 3, 4};
|
|
double backUmBuffer [6] = {1, 1, 4, 3, 3.5, 0};
|
|
int barsByPeriod = 5;
|
|
double m = (closeInPassed - lastClose) / (barsByPeriod + 1 - 1);
|
|
double um = umBuffer[i];
|
|
double backUm = backUmBuffer[i];
|
|
int turnBackInBuy = 0;
|
|
int turnBackInSell = 0;
|
|
int passedUmInBuy = 0;
|
|
int passedUmInSell = 0;
|
|
int displacement = bars / barsByPeriod;
|
|
int lengthFor = bars % 2 == 0 ? (int)(bars / 2) : (int)((bars + 1)/ 2);
|
|
for(int j = 1; j <= lengthFor; j += displacement) {
|
|
int closePos = j;
|
|
int openPos = j + displacement - 1;
|
|
int rest = displacement == 1 ? 1 : 0;
|
|
double linePoint = lastClose + m * ((int)(j / displacement) - rest);
|
|
double closeJ = rates[closePos].close;
|
|
double openJ = rates[openPos].open;
|
|
|
|
double dist = utils.absDiffInPercent(linePoint, closeJ);
|
|
double backDist = utils.absDiffInPercent(openJ, closeJ);
|
|
if(operation > 0 && openJ < closeJ && backDist > backUm) {
|
|
turnBackInBuy += 1;
|
|
}
|
|
if(operation < 0 && openJ > closeJ && backDist > backUm) {
|
|
turnBackInBuy += 1;
|
|
}
|
|
if(operation > 0 && linePoint > closeJ && dist > um) {
|
|
chartUtils.drawLine(string((string)timeCurrent + (string)bars + (string)j + "trend"), rates[bars + 1].time, closeInPassed, rates[1].time, rates[1].close);
|
|
chartUtils.drawLine(string((string)timeCurrent + (string)bars + (string)j + "linePoint"), rates[bars + 1].time, linePoint, rates[closePos].time, linePoint);
|
|
passedUmInBuy += 1;
|
|
if(turnBackInBuy > 0) {
|
|
break;
|
|
}
|
|
}
|
|
if(operation < 0 && linePoint < closeJ && dist > um) {
|
|
chartUtils.drawLine(string((string)timeCurrent + (string)bars + (string)j + "trend"), rates[bars + 1].time, closeInPassed, rates[1].time, rates[1].close);
|
|
chartUtils.drawLine(string((string)timeCurrent + (string)bars + (string)j + "linePoint"), rates[bars + 1].time, linePoint, rates[closePos].time, linePoint);
|
|
passedUmInSell += 1;
|
|
if(turnBackInSell) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(operation > 0 && passedUmInBuy > 0 && turnBackInBuy > 0) {
|
|
operation = 0;
|
|
}
|
|
if(operation < 0 && passedUmInSell > 0 && turnBackInSell > 0) {
|
|
operation = 0;
|
|
}
|
|
}
|
|
// end passed oportunity confirm
|
|
// spread confirm
|
|
double ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
|
|
double bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
|
|
double spread=ask-bid;
|
|
if(spread > spreadUmbral) {
|
|
operation = 0;
|
|
}
|
|
// end spread confirm
|
|
//macd confirm
|
|
double MACDlineBuffer[];
|
|
double signallineBuffer[];
|
|
CopyBuffer(MACDhadlingBuffer[i],0,1,2,MACDlineBuffer);
|
|
CopyBuffer(MACDhadlingBuffer[i],1,1,2,signallineBuffer);
|
|
ArraySetAsSeries(MACDlineBuffer,true);
|
|
ArraySetAsSeries(signallineBuffer,true);
|
|
double lasthist = MathAbs(MACDlineBuffer[0]-signallineBuffer[0]);
|
|
double penultimehist = MathAbs(MACDlineBuffer[1]-signallineBuffer[1]);
|
|
double diff = utils.absDiffInPercent(lasthist,penultimehist);
|
|
if(useMacDConfirm && penultimehist < lasthist && diff > macdUmbral)
|
|
operation = 0;
|
|
//end macd confirm
|
|
// TODO this confirm code there are in testing, please use numberToDivPeriod in 0 for now
|
|
if(bars >= numberToDivPeriod && consecutiveCandleToConfirmInPercentUmbral !=0 && numberToDivPeriod != 0) {
|
|
int consecutiveCandleToConfirm = 0;
|
|
int length = bars / numberToDivPeriod;
|
|
int consecutiveUmbral = consecutiveCandleToConfirmInPercentUmbral * length / 100;
|
|
for(int k = 0; k < length; k++) {
|
|
int closePos = k*numberToDivPeriod + 1;
|
|
int openPos = k*numberToDivPeriod + numberToDivPeriod;
|
|
double close = rates[closePos].close;
|
|
double open = rates[openPos].open;
|
|
if(close > open) {
|
|
consecutiveCandleToConfirm += 1;
|
|
} else {
|
|
consecutiveCandleToConfirm-=1;
|
|
}
|
|
}
|
|
if(MathAbs(consecutiveCandleToConfirm) >= consecutiveUmbral)
|
|
operation = 0;
|
|
}
|
|
//end confirm segment
|
|
if (operation != 0) {
|
|
double takeProfit = amplitude / 2;
|
|
double stopLoss = amplitude / 4;
|
|
double lotage = 0.01;
|
|
double riskInMoney = 0;
|
|
double position = 0;
|
|
double takeProfitLevel = 0;
|
|
double stopLossLevel = 0;
|
|
if(useFixedTakeProfit) {
|
|
takeProfit = amplitude;
|
|
}
|
|
if(useFixedStopLoss) {
|
|
stopLoss = 0.5;
|
|
}
|
|
bool isLong = utils.isLong(operation);
|
|
|
|
if(isLong) {
|
|
position=ask;
|
|
takeProfitLevel = NormalizeDouble(position * ((100 + takeProfit)/100), _Digits) + spread;
|
|
stopLossLevel = NormalizeDouble(position * ((100 - stopLoss)/100), _Digits) - spread;
|
|
} else {
|
|
position=bid;
|
|
takeProfitLevel = NormalizeDouble(position * ((100 - takeProfit)/100), _Digits) - spread;
|
|
stopLossLevel = NormalizeDouble(position * ((100 + stopLoss)/100), _Digits) + spread;
|
|
}
|
|
if(!useFixedLotage) {
|
|
lotage = utils.betterLotage(MaxRiskByTradeInPercent, stopLossLevel,isLong, useMinLotInTradeIfNotEnough,true);
|
|
// TODO we need calculate better the riskInMoney when the lotage is a value fixed
|
|
riskInMoney = NormalizeDouble(AccountInfoDouble(ACCOUNT_MARGIN_FREE)*(MaxRiskByTradeInPercent/100),_Digits);
|
|
}
|
|
PositionInfo tmp = createPositionInfo(-1,position,amplitude,lotage,riskInMoney,bars,timeCurrent,operation,takeProfit,takeProfitLevel,stopLoss,stopLossLevel);
|
|
positionsInfo[bars] = tmp;
|
|
cantPositionsOpen +=1;
|
|
chartUtils.drawLine(string(timeCurrent + bars), rates[bars + 1].time, closeInPassed, rates[1].time, rates[1].close);
|
|
}
|
|
}
|
|
return cantPositionsOpen;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void MakeTrade(int bars) {
|
|
ResetLastError();
|
|
//if position don't was open
|
|
bool exitPosition = exitPositionByPeriodInBars(positionsInfo, bars);
|
|
if(!exitPosition)
|
|
return;
|
|
// if position was trade
|
|
bool madeTrade = madeTradeInPosition(positionsInfo, bars);
|
|
if(madeTrade)
|
|
return;
|
|
PositionInfo currentPositionInfo = positionsInfo[bars];
|
|
bool isLong = utils.isLong(currentPositionInfo.signal);
|
|
double position = currentPositionInfo.position;
|
|
double takeProfit = currentPositionInfo.takeProfit;
|
|
double takeProfitLevel = currentPositionInfo.takeProfitLevel;
|
|
double stopLoss = currentPositionInfo.stopLoss;
|
|
double lotage = currentPositionInfo.lotage;
|
|
double stopLossLevel = currentPositionInfo.stopLossLevel;
|
|
string comment = "sl: " + (string)NormalizeDouble(stopLoss, 2) + " tp: " + (string)NormalizeDouble(takeProfit, 2);
|
|
bool orderCompleted = false;
|
|
if(isLong) {
|
|
orderCompleted = trade.Buy(lotage,_Symbol,position,stopLossLevel,takeProfitLevel,comment);
|
|
} else {
|
|
orderCompleted = trade.Sell(lotage,_Symbol,position,stopLossLevel,takeProfitLevel,comment);
|
|
}
|
|
ulong code = trade.ResultRetcode();
|
|
string order = isLong ? "buy" : "sell";
|
|
long ticket = (long)trade.ResultOrder();
|
|
string msj = "";
|
|
if( orderCompleted && code == TRADE_RETCODE_DONE) {
|
|
msj = StringFormat("(%s): ticket:(%d) ,position:(%f) ,stopLossLevel:(%f) ,takeProfitLevel:(%f), comment: (%s)", order, ticket, position, stopLossLevel, takeProfitLevel, comment);
|
|
} else {
|
|
msj = StringFormat("ERROR code(%d): in (%s) with: ticket:(%d) ,position:(%f) ,stopLossLevel:(%f) ,takeProfitLevel:(%f), comment: (%s)", code, order, ticket, position, stopLossLevel, takeProfitLevel, comment);
|
|
}
|
|
Print(msj);
|
|
Alert(msj);
|
|
currentPositionInfo.ticket = ticket;
|
|
currentPositionInfo.openPositionTime = TimeCurrent();
|
|
datetime curr = TimeCurrent();
|
|
positionsInfo[bars] = currentPositionInfo;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void checkIfClosePositionByExpiration() {
|
|
for( int i=0; i < periodInBarsLength; i++) {
|
|
int bars = periodInBars[i];
|
|
bool exitPosition = exitPositionByPeriodInBars(positionsInfo, bars);
|
|
if(!exitPosition) {
|
|
continue;
|
|
}
|
|
PositionInfo currentPositionInfo = positionsInfo[bars];
|
|
ulong timePassedInSec = TimeCurrent() - currentPositionInfo.openPositionTime;
|
|
ulong timeToClose = (int)numberPeriodsToClosePosition * bars * 60;
|
|
if(timePassedInSec >= timeToClose) {
|
|
trade.PositionClose(currentPositionInfo.ticket,tradeDeviation);
|
|
positionsInfo[bars] = createEmptyPosition(initTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void setTemporalsAmplitudes() {
|
|
// if mode test
|
|
if(modeEnv == 1) {
|
|
double periodInBarsTmp [1]= {5};
|
|
periodInBarsTmp[0] = periodSelected;
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {0.5};
|
|
amplitudeUmbralsTmp[0] = amplitudeValues;
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
return;
|
|
}
|
|
switch (temporalToAmplitude) {
|
|
case 0: {
|
|
double periodInBarsTmp [12]= {2, 4, 6, 10, 13, 15, 17, 19, 25, 27, 30, 40};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[12] = {2, 2, 2.5, 3, 4, 4.5, 4.5, 4.5, 5, 5.5, 5.5, 6.5};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 5: {
|
|
double periodInBarsTmp [1]= {5};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {2};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 10: {
|
|
double periodInBarsTmp [1]= {10};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {2.5};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 30: {
|
|
double periodInBarsTmp [1]= {30};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {3};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 50: {
|
|
double periodInBarsTmp [1]= {50};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {2.5};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 70: {
|
|
double periodInBarsTmp [1]= {70};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {3};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 100: {
|
|
double periodInBarsTmp [1]= {100};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {7.5};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 120: {
|
|
double periodInBarsTmp [1]= {120};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {4.5};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 150: {
|
|
double periodInBarsTmp [1]= {150};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {5.5};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 240: {
|
|
double periodInBarsTmp [1]= {240};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {8.5};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 500: {
|
|
double periodInBarsTmp [1]= {500};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {11};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
case 1440: {
|
|
double periodInBarsTmp [1]= {1440};
|
|
ArrayCopy(periodInBars, periodInBarsTmp, 0, 0, WHOLE_ARRAY);
|
|
double amplitudeUmbralsTmp[1] = {17};
|
|
ArrayCopy(amplitudeUmbrals, amplitudeUmbralsTmp, 0, 0, WHOLE_ARRAY);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|