fix: Partial close (once per position), Move SL to breakeven
This commit is contained in:
+58
-7
@@ -5,7 +5,7 @@
|
||||
//| Based on: ORB-All-Sessions.pine + LuxAlgo Order Block Detector |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "NANDR"
|
||||
#property version "1.34"
|
||||
#property version "1.35"
|
||||
#property strict
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
@@ -115,6 +115,7 @@ input double InpRRRatio = 1.0; // Risk:Reward Ratio
|
||||
input group "═══ Trade Management ═══"
|
||||
input double InpBreakevenTrigPips = 50.0; // Breakeven Trigger (pips)
|
||||
input double InpBreakevenOffPips = 2.0; // Breakeven Offset (pips)
|
||||
input double InpPartialCloseRatio = 0.5; // Partial Close Ratio at BE (0=disabled, 0.5=half)
|
||||
input double InpTrailingStopPips = 0.0; // Trailing Stop Pips (0=off)
|
||||
input int InpMaxTradesPerDay = 8; // Max Trades per Day
|
||||
input int InpMaxPosPerSession = 2; // Max Positions per Session
|
||||
@@ -217,6 +218,27 @@ int g_BearOBCount = 0;
|
||||
// contradict this bias are suppressed, preventing counter-trend trades.
|
||||
int g_GlobalBiasDir = 0;
|
||||
|
||||
// Tracks tickets that have already had partial close executed so it only fires once per position
|
||||
#define MAX_PARTIAL_TRACKED 20
|
||||
ulong g_PartialClosedTickets[MAX_PARTIAL_TRACKED];
|
||||
int g_PartialClosedCount = 0;
|
||||
|
||||
bool IsPartialClosed(ulong ticket)
|
||||
{
|
||||
for(int i = 0; i < g_PartialClosedCount; i++)
|
||||
if(g_PartialClosedTickets[i] == ticket) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void MarkPartialClosed(ulong ticket)
|
||||
{
|
||||
if(g_PartialClosedCount < MAX_PARTIAL_TRACKED)
|
||||
{
|
||||
g_PartialClosedTickets[g_PartialClosedCount] = ticket;
|
||||
g_PartialClosedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Daily stats
|
||||
datetime g_LastDayReset = 0;
|
||||
int g_TodayTrades = 0;
|
||||
@@ -1257,17 +1279,45 @@ void ManageOpenTrades()
|
||||
ulong ticket = g_Position.Ticket();
|
||||
int posDir = (g_Position.PositionType() == POSITION_TYPE_BUY) ? 1 : -1;
|
||||
|
||||
// Breakeven
|
||||
// Breakeven + Partial Close
|
||||
if(InpBreakevenTrigPips > 0)
|
||||
{
|
||||
double trigDist = PipsToPrice(InpBreakevenTrigPips);
|
||||
double beDist = PipsToPrice(InpBreakevenOffPips);
|
||||
double beLevel = (posDir > 0) ? entry + beDist : entry - beDist;
|
||||
bool triggered = (posDir > 0)
|
||||
? (price >= entry + trigDist && sl < beLevel)
|
||||
: (price <= entry - trigDist && (sl > beLevel || sl == 0));
|
||||
|
||||
if(posDir > 0 && price >= entry + trigDist && sl < beLevel)
|
||||
currentSL = NormalizeDouble(beLevel, (int)SymbolInfoInteger(g_Symbol, SYMBOL_DIGITS));
|
||||
else if(posDir < 0 && price <= entry - trigDist && (sl > beLevel || sl == 0))
|
||||
if(triggered)
|
||||
{
|
||||
// Step 1: partial close — fire once per position
|
||||
if(InpPartialCloseRatio > 0 && !IsPartialClosed(ticket))
|
||||
{
|
||||
double fullLots = g_Position.Volume();
|
||||
double closeLots = NormalizeLot(fullLots * InpPartialCloseRatio);
|
||||
double minLot = SymbolInfoDouble(g_Symbol, SYMBOL_VOLUME_MIN);
|
||||
if(closeLots >= minLot)
|
||||
{
|
||||
bool partResult = (posDir > 0)
|
||||
? g_Trade.Sell(closeLots, g_Symbol, 0, 0, 0,
|
||||
StringFormat("NANDR|PartialClose|%.0fpips", InpBreakevenTrigPips))
|
||||
: g_Trade.Buy(closeLots, g_Symbol, 0, 0, 0,
|
||||
StringFormat("NANDR|PartialClose|%.0fpips", InpBreakevenTrigPips));
|
||||
if(partResult)
|
||||
{
|
||||
MarkPartialClosed(ticket);
|
||||
PrintFormat("NANDR EA: Partial close %.2f lots at %.2f (%.0f pips profit). Ticket=%llu",
|
||||
closeLots, price, InpBreakevenTrigPips, ticket);
|
||||
}
|
||||
else
|
||||
PrintFormat("NANDR EA: Partial close failed. Error=%d Ticket=%llu",
|
||||
GetLastError(), ticket);
|
||||
}
|
||||
}
|
||||
// Step 2: move SL to breakeven
|
||||
currentSL = NormalizeDouble(beLevel, (int)SymbolInfoInteger(g_Symbol, SYMBOL_DIGITS));
|
||||
}
|
||||
}
|
||||
|
||||
// Trailing stop
|
||||
@@ -1310,8 +1360,9 @@ void CheckDailyReset()
|
||||
g_TodayLosses = 0;
|
||||
g_TodayPnL = 0;
|
||||
g_DayStartEquity = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
g_TradingHalted = false;
|
||||
g_GlobalBiasDir = 0; // clear day bias — first session breakout will re-establish it
|
||||
g_TradingHalted = false;
|
||||
g_GlobalBiasDir = 0; // clear day bias — first session breakout will re-establish it
|
||||
g_PartialClosedCount = 0; // clear partial close tracker for the new day
|
||||
|
||||
// Reset all session ORB data for the new day
|
||||
for(int s = 0; s < g_SessionCount; s++)
|
||||
|
||||
Reference in New Issue
Block a user