ProRealCode - Trading & Coding with ProRealTime™
Hello everyone,
I would like to reproduce an existing MT5 trading logic in ProRealTime / ProBacktest, mainly in order to test it on the longest possible historical DE40 data series available in PRT.
The focus is not on optimizing the entry logic, but on the capital management.
The basic idea is:
In short:
Capital target fixed – TP price dynamic.
This is not intended as a martingale system and not as a classic fixed-distance grid. The position size remains constant.
Example:
With two open positions, the common TP should be calculated so that both positions together produce the predefined basket profit.
If a third position is added, the common TP should be recalculated so that all three positions together still reach the same fixed capital target.
The main purpose of the backtest is to evaluate the capital-management behaviour over a long DE40 history.
The statistics I am especially interested in are:
I will add the existing MT5 code below. It should be understood as a reference implementation of the intended logic and does not need to be translated line by line.
If SET TARGET %PROFIT is not suitable for cumulative positions, the common basket target price would need to be calculated explicitly and the complete position closed at that price.
The underlying entry logic is simple and is not the main point of this discussion.
Any help with a clean ProRealTime / ProBacktest implementation of this capital-management logic would be appreciated.
MT5 code follows here:
(Please note: the MT5 code is provided only as a reference for the trading and capital-management logic. I am not asking for a review of the EA’s MT5-specific robustness, retry handling, logging, persistence, or broker execution details.)
//+——————————————————————+
//| D209_1HL_D522_D1HighLow_Basket.mq5 |
//| https://www.dkatle.com |
//| Copyright dkatle 2026 |
//+——————————————————————+
#property strict
#property copyright “dkatle 2026”
#property link “https://www.dkatle.com”
#property version “6.4”
#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>
CTrade trade;
CPositionInfo posInfo;
// — Input Parameter —
input string TradeComment = “D209 1HL D522 D1HiLo Basket”;
input long Magic = 2090522063
input group “Kapital & Basket Einstellungen”
input double InitialVirtualCapital = 1000.0;
input double BasketTPPercent = 5.0;
input bool CumulateOrders = true;
input group “Handels Parameter”
input double FixedLotSize = 0.1;
input double StopLossPercent = 0.0;
input double TakeProfitPercent = 2.5;
input group “Einstiegs-Zeitpunkt (Slot)”
input string InpHolidays = “01.01, 01.05, 03.10, 24.12, 25.12, 26.12, 31.12”;
input int BlockMonth1 = 0;
input int BlockMonth2 = 0;
input int BlockMonth3 = 0;
input int BlockMonth4 = 0;
input bool UseBerlinOffset = false;
input int BerlinOffsetHours = +1;
input bool InpTradeMonday = false;
input bool InpTradeTuesday = true;
input bool InpTradeWednesday = false;
input bool InpTradeThursday = false;
input bool InpTradeFriday = false;
input int InpEntryHour = 09;
input int InpEntryMinute = 00;
input group “Ausstiegs-Zeitpunkt (Slot & Wochentag für Einzelläufer)”
input bool InpExitEnabled = false;
input bool InpExitMonday = false;
input bool InpExitTuesday = true;
input bool InpExitWednesday = false;
input bool InpExitThursday = false;
input bool InpExitFriday = true;
input int InpExitHour = 22;
input int InpExitMinute = 00;
input group “Robustheit / Retry”
input int EntryWindowSeconds = 60;
input int RetryIntervalMs = 500;
input int CloseRetryIntervalHours = 1;
input int MaxSpreadPoints = 100;
input int MaxSlippagePoints = 50;
// — Globale Variablen —
string lblStart, lblCurr, lblTarget, logFileName;
datetime lastProcessedEntrySlot = 0;
ulong lastEntryAttemptMs = 0;
bool basketActive = false;
double basketLockedTarget = 0.0;
bool targetCloseActive = false;
double targetCloseLockedTarget = 0.0;
// — Hilfs-Namen für globale Variablen im Terminal —
string GV_TargetName(ulong ticket) { return “D113_Exit_” + (string)Magic + “_” + (string)ticket + “_Target”; }
string GV_NextName(ulong ticket) { return “D113_Exit_” + (string)Magic + “_” + (string)ticket + “_Next”; }
string GV_LastEntrySlotName() { return “D113_LastEntry_” + (string)Magic + “_” + _Symbol; }
string GV_BasketTargetName() { return “D113_BasketTarget_” + (string)Magic + “_” + _Symbol; }
string GV_TargetCloseName() { return “D113_BasketClose_” + (string)Magic + “_” + _Symbol; }
//+——————————————————————+
//| Hilfsfunktionen |
//+——————————————————————+
int GetOpenPositionsCount()
{
int count = 0;
for(int i = PositionsTotal() – 1; i >= 0; i–)
{
if(posInfo.SelectByIndex(i) && posInfo.Magic() == Magic && posInfo.Symbol() == _Symbol)
count++;
}
return count;
}
bool IsTradeRetcodeAccepted()
{
uint rc = trade.ResultRetcode();
return (rc == TRADE_RETCODE_DONE ||
rc == TRADE_RETCODE_DONE_PARTIAL ||
rc == TRADE_RETCODE_PLACED);
}
string TradeResultText()
{
return “Retcode=” + (string)trade.ResultRetcode() +
” (” + trade.ResultRetcodeDescription() + “)” +
“, Order=” + (string)trade.ResultOrder() +
“, Deal=” + (string)trade.ResultDeal();
}
bool ClosePositionVerified(ulong ticket)
{
if(!PositionSelectByTicket(ticket))
return true;
trade.SetDeviationInPoints(MaxSlippagePoints);
ResetLastError();
bool requestOk = trade.PositionClose(ticket);
bool accepted = requestOk && IsTradeRetcodeAccepted();
bool stillOpen = PositionSelectByTicket(ticket);
if(accepted && !stillOpen)
return true;
Print(“D308 CLOSE nicht vollständig ausgeführt. Ticket=”, ticket,
“, RequestOK=”, requestOk,
“, “, TradeResultText(),
“, LastError=”, GetLastError());
return false;
}
void MarkEntrySlotProcessed(datetime slotStart)
{
lastProcessedEntrySlot = slotStart;
GlobalVariableSet(GV_LastEntrySlotName(), (double)slotStart);
}
void ActivateBasket(double target)
{
basketActive = true;
basketLockedTarget = target;
GlobalVariableSet(GV_BasketTargetName(), target);
}
void DeactivateBasket()
{
basketActive = false;
basketLockedTarget = 0.0;
string gv = GV_BasketTargetName();
if(GlobalVariableCheck(gv))
GlobalVariableDel(gv);
}
void ActivateTargetClose(double target)
{
targetCloseActive = true;
targetCloseLockedTarget = target;
GlobalVariableSet(GV_TargetCloseName(), target);
}
void DeactivateTargetClose()
{
targetCloseActive = false;
targetCloseLockedTarget = 0.0;
string gv = GV_TargetCloseName();
if(GlobalVariableCheck(gv))
GlobalVariableDel(gv);
}
string FormatGermanNumber(double value)
{
string s = DoubleToString(value, 2);
StringReplace(s, “.”, “,”);
int commaPos = StringFind(s, “,”);
if(commaPos > 3)
{
for(int i = commaPos – 3; i > 0; i -= 3)
s = StringSubstr(s, 0, i) + “.” + StringSubstr(s, i);
}
return s;
}
void UpdateDisplay()
{
double realizedProfit = 0;
double floatingProfit = 0;
datetime startDate = 0;
CalculateCapitalMetrics(realizedProfit, floatingProfit, startDate);
double securedCapital = InitialVirtualCapital + realizedProfit;
double virtualCapital = securedCapital + floatingProfit;
double nextTarget = CalculateNextTarget(securedCapital);
int openCount = GetOpenPositionsCount();
string dateStr = (startDate > 0) ? TimeToString(startDate, TIME_DATE) : “Kein Trade”;
string txtStart = “Start Capital (” + dateStr + “) : ” + FormatGermanNumber(InitialVirtualCapital) + ” EUR”;
string txtCurr = “Virtual Capital (Equity) : ” + FormatGermanNumber(virtualCapital) + ” EUR”;
string txtTarget = “Next Capital Target (+ ” + DoubleToString(BasketTPPercent, 1) + “%) : ” + FormatGermanNumber(nextTarget) + ” EUR”;
if(basketActive)
txtTarget = “Basket Target LOCKED (+ ” + DoubleToString(BasketTPPercent, 1) + “%) : ” + FormatGermanNumber(basketLockedTarget) + ” EUR”;
if(targetCloseActive)
{
string mode = basketActive ? “BASKET” : “SINGLE”;
txtTarget = mode + ” TARGET CLOSE ACTIVE : ” + FormatGermanNumber(targetCloseLockedTarget) + ” EUR”;
}
else if(openCount == 1 && !basketActive)
{
txtTarget = “Single Capital Target (+ ” + DoubleToString(BasketTPPercent, 1) + “%) : ” + FormatGermanNumber(nextTarget) + ” EUR”;
}
CreateOrUpdateLabel(lblStart, txtStart, 35);
CreateOrUpdateLabel(lblCurr, txtCurr, 55);
CreateOrUpdateLabel(lblTarget, txtTarget, 75);
ChartRedraw();
}
void CreateOrUpdateLabel(string name, string text, int yDist)
{
if(ObjectFind(0, name) < 0)
{
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 15);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 8);
ObjectSetString(0, name, OBJPROP_FONT, “Arial”);
}
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, yDist);
ObjectSetString(0, name, OBJPROP_TEXT, text);
}
//+——————————————————————+
//| Daten- und Log-Funktionen |
//+——————————————————————+
string SanitizeFileName(string s)
{
string bad = “\/:*?”<>|”;
for(int i = 0; i < StringLen(bad); i++)
StringReplace(s, StringSubstr(bad, i, 1), “_”);
StringReplace(s, ” “, “_”);
return s;
}
void LogTradeEvent(string line)
{
if(StringLen(logFileName) == 0) return;
int handle = FileOpen(logFileName, FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI);
if(handle == INVALID_HANDLE)
{
handle = FileOpen(logFileName, FILE_WRITE|FILE_CSV|FILE_ANSI);
if(handle == INVALID_HANDLE) return;
FileWrite(handle, “Time;Magic;Event;Symbol;Lots;Price;SL;TP;Comment;Info;Spread;Swap”);
}
FileSeek(handle, 0, SEEK_END);
FileWrite(handle, line);
FileClose(handle);
}
//+——————————————————————+
//| Handels-Kernfunktionen |
//+——————————————————————+
double RoundLotFixed(double lotsInput)
{
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(step <= 0) step = 0.1;
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
if(minLot <= 0) minLot = 0.01;
double r = MathRound(lotsInput / step) * step;
return NormalizeDouble(MathMax(r, minLot), 2);
}
bool TryBuyWithFallback(double lotsInput, double price, double sl, double tp, string comment)
{
ulong nowMs = GetTickCount64();
int retryMs = RetryIntervalMs;
if(retryMs < 0) retryMs = 0;
if(lastEntryAttemptMs > 0 && (nowMs – lastEntryAttemptMs) < (ulong)retryMs)
return false;
lastEntryAttemptMs = nowMs;
double tryLots = RoundLotFixed(lotsInput);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(ask <= 0 || bid <= 0)
return false;
double spreadPoints = (ask – bid) / _Point;
if(spreadPoints > MaxSpreadPoints)
return false;
trade.SetDeviationInPoints(MaxSlippagePoints);
ResetLastError();
bool requestOk = trade.Buy(tryLots, _Symbol, ask, sl, tp, comment);
if(requestOk && IsTradeRetcodeAccepted())
{
LogTradeEvent(TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + “;” +
(string)Magic + “;ORDER_OK;” + _Symbol + “;” +
DoubleToString(tryLots, 2) + “;” +
DoubleToString(ask, _Digits) + “;” +
DoubleToString(sl, _Digits) + “;” +
DoubleToString(tp, _Digits) + “;” +
TradeComment + “;” + TradeResultText() + “;” +
DoubleToString(spreadPoints, 1) + “;0”);
return true;
}
Print(“D308 BUY fehlgeschlagen/abgelehnt. RequestOK=”, requestOk,
“, “, TradeResultText(),
“, LastError=”, GetLastError());
return false;
}
//+——————————————————————+
//| Filter-Funktionen |
//+——————————————————————+
bool IsHoliday(MqlDateTime &dt)
{
string date_str = StringFormat(“%02d.%02d”, dt.day, dt.mon);
if(StringFind(InpHolidays, date_str) >= 0) return true;
return false;
}
bool IsMonthBlocked(int m)
{
if(m == BlockMonth1 || m == BlockMonth2 || m == BlockMonth3) return true;
if(BlockMonth4 != 0 && m == BlockMonth4) return true;
return false;
}
bool IsWeekdayAllowed(int w)
{
if(w == 1 && InpTradeMonday) return true;
if(w == 2 && InpTradeTuesday) return true;
if(w == 3 && InpTradeWednesday) return true;
if(w == 4 && InpTradeThursday) return true;
if(w == 5 && InpTradeFriday) return true;
return false;
}
bool IsExitWeekdayAllowed(int w)
{
if(w == 1 && InpExitMonday) return true;
if(w == 2 && InpExitTuesday) return true;
if(w == 3 && InpExitWednesday) return true;
if(w == 4 && InpExitThursday) return true;
if(w == 5 && InpExitFriday) return true;
return false;
}
//+——————————————————————+
//| Zeit-Management für den Ausstieg des Einzelläufers |
//+——————————————————————+
datetime CalculateNextExit(datetime fromTime)
{
MqlDateTime dt;
TimeToStruct(fromTime, dt);
dt.hour = InpExitHour;
dt.min = InpExitMinute;
dt.sec = 0;
datetime target = StructToTime(dt);
while(target <= fromTime || !IsExitWeekdayAllowed(dt.day_of_week))
{
target += 86400;
TimeToStruct(target, dt);
dt.hour = InpExitHour;
dt.min = InpExitMinute;
dt.sec = 0;
target = StructToTime(dt);
}
return target;
}
void RegisterAllOpenPositionsTargets()
{
if(!InpExitEnabled) return;
for(int i = PositionsTotal() – 1; i >= 0; i–)
{
if(posInfo.SelectByIndex(i) && posInfo.Magic() == Magic && posInfo.Symbol() == _Symbol)
{
ulong ticket = posInfo.Ticket();
if(!GlobalVariableCheck(GV_TargetName(ticket)))
{
datetime target = CalculateNextExit((datetime)posInfo.Time());
GlobalVariableSet(GV_TargetName(ticket), (double)target);
GlobalVariableSet(GV_NextName(ticket), (double)target);
}
}
}
}
//+——————————————————————+
//| Zeit-Ausstieg |
//+——————————————————————+
void CheckAndClosePositions()
{
if(!InpExitEnabled) return;
if(basketActive || targetCloseActive) return;
if(GetOpenPositionsCount() != 1) return;
for(int i = PositionsTotal() – 1; i >= 0; i–)
{
if(posInfo.SelectByIndex(i) && posInfo.Magic() == Magic && posInfo.Symbol() == _Symbol)
{
ulong ticket = posInfo.Ticket();
string gvT = GV_TargetName(ticket);
string gvN = GV_NextName(ticket);
if(!GlobalVariableCheck(gvN)) continue;
if(TimeCurrent() < (datetime)GlobalVariableGet(gvN)) continue;
double currentProfit = posInfo.Profit() + posInfo.Swap() + posInfo.Commission();
if(currentProfit <= 0.0) continue;
if(ClosePositionVerified(ticket))
{
if(GlobalVariableCheck(gvT)) GlobalVariableDel(gvT);
if(GlobalVariableCheck(gvN)) GlobalVariableDel(gvN);
LogTradeEvent(TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + “;” +
(string)Magic + “;SINGLE_EXIT_SLOT_PROFIT;” + _Symbol +
“;0;0;0;0;” + TradeComment +
“;ClosedInProfit=” + DoubleToString(currentProfit, 2) + “;0;0”);
UpdateDisplay();
}
else
{
GlobalVariableSet(gvN, (double)(TimeCurrent() + CloseRetryIntervalHours * 3600));
}
}
}
}
//+——————————————————————+
//| Kapital- & Basket-Berechnungen |
//+——————————————————————+
void CalculateCapitalMetrics(double &realizedProfit, double &floatingProfit, datetime &startDate)
{
realizedProfit = 0;
floatingProfit = 0;
startDate = 0;
if(HistorySelect(0, TimeCurrent() + 86400))
{
int totalDeals = HistoryDealsTotal();
for(int i = 0; i < totalDeals; i++)
{
ulong ticket = HistoryDealGetTicket(i);
if(ticket > 0)
{
long dealMagic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
string dealSymbol = HistoryDealGetString(ticket, DEAL_SYMBOL);
if(dealMagic == Magic && dealSymbol == _Symbol)
{
datetime dealTime = (datetime)HistoryDealGetInteger(ticket, DEAL_TIME);
if(startDate == 0 || dealTime < startDate)
startDate = dealTime;
long dealEntry = HistoryDealGetInteger(ticket, DEAL_ENTRY);
if(dealEntry == DEAL_ENTRY_OUT || dealEntry == DEAL_ENTRY_INOUT)
{
realizedProfit += HistoryDealGetDouble(ticket, DEAL_PROFIT)
+ HistoryDealGetDouble(ticket, DEAL_SWAP)
+ HistoryDealGetDouble(ticket, DEAL_COMMISSION);
}
}
}
}
}
int openTotal = PositionsTotal();
for(int i = 0; i < openTotal; i++)
{
if(posInfo.SelectByIndex(i) && posInfo.Magic() == Magic && posInfo.Symbol() == _Symbol)
{
floatingProfit += posInfo.Profit() + posInfo.Swap() + posInfo.Commission();
}
}
}
double CalculateNextTarget(double securedCapital)
{
if(BasketTPPercent <= 0.0)
return DBL_MAX;
double target = InitialVirtualCapital;
double multiplier = 1.0 + (BasketTPPercent / 100.0);
while(securedCapital >= target * multiplier)
target = target * multiplier;
return NormalizeDouble(target * multiplier, 2);
}
//+——————————————————————+
//| Kapitalziel / Basket-State-Machine |
//+——————————————————————+
void CheckAndCloseBasket()
{
double realizedProfit = 0;
double floatingProfit = 0;
datetime startDate = 0;
CalculateCapitalMetrics(realizedProfit, floatingProfit, startDate);
double securedCapital = InitialVirtualCapital + realizedProfit;
double virtualCapital = securedCapital + floatingProfit;
double dynamicTarget = CalculateNextTarget(securedCapital);
int openCount = GetOpenPositionsCount();
if(openCount == 0)
{
bool hadBasket = basketActive;
bool hadTargetClose = targetCloseActive;
double completedTarget = targetCloseActive ? targetCloseLockedTarget : basketLockedTarget;
if(targetCloseActive)
DeactivateTargetClose();
if(basketActive)
DeactivateBasket();
if(hadTargetClose)
{
LogTradeEvent(TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + “;” +
(string)Magic + “;CAPITAL_TARGET_CLOSE_SUCCESS;” + _Symbol +
“;0;0;0;0;” + TradeComment +
“;AllPositionsClosed;Mode=” + (hadBasket ? “BASKET” : “SINGLE”) +
“,LockedTarget=” + DoubleToString(completedTarget, 2) + “;0;0”);
}
if(hadBasket || hadTargetClose)
UpdateDisplay();
return;
}
if(!basketActive && openCount >= 2)
{
ActivateBasket(dynamicTarget);
LogTradeEvent(TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + “;” +
(string)Magic + “;BASKET_ACTIVATED;” + _Symbol +
“;0;0;0;0;” + TradeComment +
“;OpenPositions=” + (string)openCount +
“,LockedTarget=” + DoubleToString(basketLockedTarget, 2) +
“,VirtualCap=” + DoubleToString(virtualCapital, 2) + “;0;0”);
UpdateDisplay();
}
double triggerTarget = basketActive ? basketLockedTarget : dynamicTarget;
if(basketActive && triggerTarget <= 0.0)
{
basketLockedTarget = dynamicTarget;
triggerTarget = dynamicTarget;
GlobalVariableSet(GV_BasketTargetName(), basketLockedTarget);
}
if(!targetCloseActive && virtualCapital >= triggerTarget)
{
ActivateTargetClose(triggerTarget);
string eventName = basketActive ? “BASKET_TARGET_TRIGGER” : “SINGLE_CAPITAL_TARGET_TRIGGER”;
LogTradeEvent(TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + “;” +
(string)Magic + “;” + eventName + “;” + _Symbol +
“;0;0;0;0;” + TradeComment +
“;OpenPositions=” + (string)openCount +
“,VirtualCap=” + DoubleToString(virtualCapital, 2) +
“,Target=” + DoubleToString(triggerTarget, 2) + “;0;0”);
UpdateDisplay();
}
if(!targetCloseActive)
return;
int closedCount = 0;
for(int i = PositionsTotal() – 1; i >= 0; i–)
{
if(posInfo.SelectByIndex(i) && posInfo.Magic() == Magic && posInfo.Symbol() == _Symbol)
{
ulong ticket = posInfo.Ticket();
if(ClosePositionVerified(ticket))
{
string gvT = GV_TargetName(ticket);
string gvN = GV_NextName(ticket);
if(GlobalVariableCheck(gvT)) GlobalVariableDel(gvT);
if(GlobalVariableCheck(gvN)) GlobalVariableDel(gvN);
closedCount++;
}
}
}
int remaining = GetOpenPositionsCount();
if(remaining == 0)
{
bool wasBasket = basketActive;
double completedTarget = targetCloseLockedTarget;
DeactivateTargetClose();
if(basketActive)
DeactivateBasket();
LogTradeEvent(TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + “;” +
(string)Magic + “;CAPITAL_TARGET_CLOSE_SUCCESS;” + _Symbol +
“;0;0;0;0;” + TradeComment +
“;AllPositionsClosed;Mode=” + (wasBasket ? “BASKET” : “SINGLE”) +
“,LockedTarget=” + DoubleToString(completedTarget, 2) +
“,VirtualCapAtTrigger=” + DoubleToString(virtualCapital, 2) + “;0;0”);
UpdateDisplay();
}
else if(closedCount > 0)
{
LogTradeEvent(TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + “;” +
(string)Magic + “;CAPITAL_TARGET_CLOSE_PROGRESS;” + _Symbol +
“;0;0;0;0;” + TradeComment +
“;ClosedNow=” + (string)closedCount +
“,Remaining=” + (string)remaining +
“,Mode=” + (basketActive ? “BASKET” : “SINGLE”) +
“,LockedTarget=” + DoubleToString(targetCloseLockedTarget, 2) + “;0;0”);
UpdateDisplay();
}
}
//+——————————————————————+
//| Init / Deinit |
//+——————————————————————+
int OnInit()
{
if(InitialVirtualCapital <= 0.0 ||
BasketTPPercent <= 0.0 ||
FixedLotSize <= 0.0 ||
EntryWindowSeconds <= 0 ||
RetryIntervalMs < 0 ||
MaxSpreadPoints < 0 ||
MaxSlippagePoints < 0)
{
Print(“D308: Ungültige Eingabeparameter. EA wird nicht gestartet.”);
return(INIT_PARAMETERS_INCORRECT);
}
trade.SetExpertMagicNumber(Magic);
trade.SetDeviationInPoints(MaxSlippagePoints);
lblStart = “D113_Lbl_Start_” + (string)Magic;
lblCurr = “D113_Lbl_Curr_” + (string)Magic;
lblTarget = “D113_Lbl_Target_” + (string)Magic;
logFileName = “D113_Log_” + _Symbol + “_” + SanitizeFileName(TradeComment) + “_” + (string)Magic + “.csv”;
string gvEntry = GV_LastEntrySlotName();
if(GlobalVariableCheck(gvEntry))
lastProcessedEntrySlot = (datetime)GlobalVariableGet(gvEntry);
string gvBasket = GV_BasketTargetName();
if(GlobalVariableCheck(gvBasket))
{
basketLockedTarget = GlobalVariableGet(gvBasket);
basketActive = (basketLockedTarget > 0.0);
}
string gvClose = GV_TargetCloseName();
if(GlobalVariableCheck(gvClose))
{
targetCloseLockedTarget = GlobalVariableGet(gvClose);
targetCloseActive = (targetCloseLockedTarget > 0.0);
}
int openCountInit = GetOpenPositionsCount();
if(!basketActive && openCountInit >= 2)
{
double rp = 0.0, fp = 0.0;
datetime sd = 0;
CalculateCapitalMetrics(rp, fp, sd);
double secured = InitialVirtualCapital + rp;
ActivateBasket(CalculateNextTarget(secured));
}
if(openCountInit == 0)
{
if(targetCloseActive) DeactivateTargetClose();
if(basketActive) DeactivateBasket();
}
RegisterAllOpenPositionsTargets();
UpdateDisplay();
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectDelete(0, lblStart);
ObjectDelete(0, lblCurr);
ObjectDelete(0, lblTarget);
}
//+——————————————————————+
//| OnTick Logic |
//+——————————————————————+
void OnTick()
{
CheckAndCloseBasket();
if(targetCloseActive)
return;
CheckAndClosePositions();
MqlDateTime t;
datetime evalTime = TimeCurrent();
if(UseBerlinOffset)
evalTime += BerlinOffsetHours * 3600;
TimeToStruct(evalTime, t);
if(IsHoliday(t)) return;
if(IsMonthBlocked(t.mon)) return;
if(!IsWeekdayAllowed(t.day_of_week)) return;
MqlDateTime slot = t;
slot.hour = InpEntryHour;
slot.min = InpEntryMinute;
slot.sec = 0;
datetime slotStart = StructToTime(slot);
long diff = (long)evalTime – (long)slotStart;
if(diff >= 0 && diff <= EntryWindowSeconds && lastProcessedEntrySlot != slotStart)
{
int shift = 1;
MqlDateTime dtPrev;
TimeToStruct(iTime(_Symbol, PERIOD_D1, 1), dtPrev);
if(dtPrev.day_of_week == 0)
shift = 2;
if(iLow(_Symbol, PERIOD_D1, 0) < iLow(_Symbol, PERIOD_D1, shift) ||
iHigh(_Symbol, PERIOD_D1, 0) < iHigh(_Symbol, PERIOD_D1, shift))
{
if(CumulateOrders || !PositionSelectByMagic(Magic))
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl = 0.0;
double tp = 0.0;
if(StopLossPercent > 0.0)
sl = NormalizeDouble(ask * (1.0 – StopLossPercent / 100.0), _Digits);
if(TakeProfitPercent > 0.0)
tp = NormalizeDouble(ask * (1.0 + TakeProfitPercent / 100.0), _Digits);
if(TryBuyWithFallback(FixedLotSize, ask, sl, tp, TradeComment))
{
RegisterAllOpenPositionsTargets();
MarkEntrySlotProcessed(slotStart);
UpdateDisplay();
}
}
}
else
{
MarkEntrySlotProcessed(slotStart);
}
}
}
bool PositionSelectByMagic(long mg)
{
for(int i = PositionsTotal() – 1; i >= 0; i–)
{
if(posInfo.SelectByIndex(i) && posInfo.Magic() == mg && posInfo.Symbol() == _Symbol)
return true;
}
return false;
}
Describe what this topic is trying to build, in plain English, and ProRealAI writes the ProRealTime™ indicator, screener or system for you.
DE40 : Capital Management with a Dynamic Basket TP – Implementation
This topic contains 1 voice and has 0 replies.
| Forum: | ProOrder: Automatischer Handel & Backtesting |
| Language: | German |
| Started: | 09/29/2026 |
| Status: | Active |
| Attachments: | No files |
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.