July psychology scorecard: tilt days and wins
Re: July psychology scorecard: tilt days and wins
Since cTrader natively runs C# (.NET), you can build this with a much cleaner event-driven architecture than Pine Script. Instead of continuously polling states in a loop, cTrader’s OnTick() and Positions.Closed event handlers allow for immediate, millisecond-accurate execution when a risk threshold is breached.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: July psychology scorecard: tilt days and wins
Here is the complete cBot framework. It utilizes cTrader’s native UI elements to build the HUD directly on the chart and handles the daily rollovers, event subscriptions, and position sizing dynamically.
Code: Select all
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ProDisciplineFramework : Robot
{
// ==============================================================================
// 1. INSTITUTIONAL RISK PARAMETERS
// ==============================================================================
[Parameter("Max Daily Drawdown (%)", Group = "Risk Management", DefaultValue = 2.0, MinValue = 0.1, Step = 0.1)]
public double MaxDailyDrawdownPct { get; set; }
[Parameter("Max Consecutive Losses", Group = "Risk Management", DefaultValue = 3)]
public int MaxConsecutiveLosses { get; set; }
[Parameter("Post-Loss Cooldown (Mins)", Group = "Risk Management", DefaultValue = 10)]
public int RevengeCooldownMins { get; set; }
// ==============================================================================
// 2. STRESS PROTOCOL & SIZING
// ==============================================================================
[Parameter("Engage Stress Protocol", Group = "Life Stress Protocol", DefaultValue = false)]
public bool StressMode { get; set; }
[Parameter("Stress Sizing Exposure (%)", Group = "Life Stress Protocol", DefaultValue = 25.0, MinValue = 1.0, Step = 1.0)]
public double StressExposurePct { get; set; }
[Parameter("Base Risk Per Trade (%)", Group = "Execution", DefaultValue = 1.0, MinValue = 0.1, Step = 0.1)]
public double BaseRiskPct { get; set; }
// ==============================================================================
// STATE VARIABLES
// ==============================================================================
private double _startOfDayEquity;
private DateTime _currentSessionDate;
private bool _isDailyLockout;
private int _consecutiveLosses;
private DateTime _lastLossTime;
// UI Elements
private TextBlock _statusText;
private TextBlock _ddText;
private TextBlock _streakText;
private TextBlock _stressText;
protected override void OnStart()
{
// Initialize session tracking
_currentSessionDate = Server.Time.Date;
_startOfDayEquity = Account.Equity;
// Subscribe to position events for consecutive loss & cooldown tracking
Positions.Closed += OnPositionClosed;
// Build HUD
InitializeUI();
}
protected override void OnTick()
{
CheckSessionRollover();
EnforceDailyDrawdown();
UpdateUI();
}
// ==============================================================================
// EVENT HANDLERS & RISK LOGIC
// ==============================================================================
private void OnPositionClosed(PositionClosedEventArgs args)
{
// Only track trades opened by this framework (or remove condition to track manual trades)
if (args.Position.SymbolName != SymbolName) return;
if (args.Position.NetProfit < 0)
{
_lastLossTime = Server.Time;
_consecutiveLosses++;
}
else
{
_consecutiveLosses = 0; // Reset streak on a win
}
}
private void CheckSessionRollover()
{
if (Server.Time.Date != _currentSessionDate)
{
_currentSessionDate = Server.Time.Date;
_startOfDayEquity = Account.Equity;
_isDailyLockout = false;
_consecutiveLosses = 0;
Print("New trading session started. Risk parameters reset.");
}
}
private void EnforceDailyDrawdown()
{
if (_isDailyLockout) return;
double currentDrawdownPct = ((_startOfDayEquity - Account.Equity) / _startOfDayEquity) * 100;
if (currentDrawdownPct >= MaxDailyDrawdownPct)
{
_isDailyLockout = true;
FlattenAllPositions();
Print($"CIRCUIT BREAKER: Max Daily Drawdown ({MaxDailyDrawdownPct}%) breached. Flattening.");
}
}
private void FlattenAllPositions()
{
foreach (var position in Positions.FindAll("DisciplineFramework", SymbolName))
{
ClosePosition(position);
}
}
// ==============================================================================
// EXECUTION GATES & SIZING
// ==============================================================================
private bool IsCooldownActive()
{
if (_lastLossTime == default) return false;
return (Server.Time - _lastLossTime).TotalMinutes < RevengeCooldownMins;
}
private bool CanTrade()
{
if (_isDailyLockout) return false;
if (_consecutiveLosses >= MaxConsecutiveLosses) return false;
if (IsCooldownActive()) return false;
return true;
}
private double GetCalculatedVolume()
{
// Calculate raw risk amount based on equity
double riskAmount = Account.Equity * (BaseRiskPct / 100);
// Apply Stress Protocol Haircut
if (StressMode)
{
riskAmount *= (StressExposurePct / 100);
}
// Convert raw amount to standardized lot units based on standard leverage/SL math
// (Placeholder conversion: 1 standard lot per $1000 at risk)
double rawVolume = (riskAmount / 1000) * 100000;
return Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
}
// ==============================================================================
// PLACEHOLDER STRATEGY LOGIC
// ==============================================================================
protected override void OnBar()
{
// Simple logic placeholder (e.g., inside bar or engulfing setup)
bool goLong = Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1) && Bars.ClosePrices.Last(2) < Bars.OpenPrices.Last(2);
bool goShort = Bars.ClosePrices.Last(1) < Bars.OpenPrices.Last(1) && Bars.ClosePrices.Last(2) > Bars.OpenPrices.Last(2);
if (CanTrade())
{
if (goLong && Positions.Count(p => p.TradeType == TradeType.Buy) == 0)
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, GetCalculatedVolume(), "DisciplineFramework", 15, 30);
}
else if (goShort && Positions.Count(p => p.TradeType == TradeType.Sell) == 0)
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, GetCalculatedVolume(), "DisciplineFramework", 15, 30);
}
}
}
// ==============================================================================
// PRO UI DASHBOARD
// ==============================================================================
private void InitializeUI()
{
var grid = new Grid(2, 4)
{
BackgroundColor = Color.FromArgb(200, 18, 18, 18),
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom,
Margin = 10,
};
var styleText = new Style();
styleText.Set(ControlProperty.ForegroundColor, Color.Gray);
styleText.Set(ControlProperty.Margin, new Thickness(5));
styleText.Set(ControlProperty.FontSize, 10);
// Headers
grid.AddChild(new TextBlock { Text = "SYSTEM STATUS", Style = styleText }, 0, 0);
grid.AddChild(new TextBlock { Text = "DD %", Style = styleText }, 0, 1);
grid.AddChild(new TextBlock { Text = "STREAK", Style = styleText }, 0, 2);
grid.AddChild(new TextBlock { Text = "STRESS MODE", Style = styleText }, 0, 3);
// Dynamic Texts
_statusText = new TextBlock { Style = styleText, ForegroundColor = Color.Teal, FontWeight = FontWeight.Bold };
_ddText = new TextBlock { Style = styleText };
_streakText = new TextBlock { Style = styleText };
_stressText = new TextBlock { Style = styleText, Text = StressMode ? "ENGAGED" : "STANDBY", ForegroundColor = StressMode ? Color.MediumPurple : Color.Gray };
grid.AddChild(_statusText, 1, 0);
grid.AddChild(_ddText, 1, 1);
grid.AddChild(_streakText, 1, 2);
grid.AddChild(_stressText, 1, 3);
var border = new Border
{
BorderColor = Color.FromArgb(255, 40, 40, 40),
BorderThickness = 1,
Child = grid
};
Chart.AddControl(border);
}
private void UpdateUI()
{
double currentDrawdownPct = ((_startOfDayEquity - Account.Equity) / _startOfDayEquity) * 100;
currentDrawdownPct = Math.Max(0, currentDrawdownPct);
// Drawdown Update
_ddText.Text = $"{currentDrawdownPct:F2}% / {MaxDailyDrawdownPct:F1}%";
_ddText.ForegroundColor = currentDrawdownPct > (MaxDailyDrawdownPct * 0.8) ? Color.Orange : Color.Silver;
// Streak Update
_streakText.Text = $"{_consecutiveLosses} Loss";
_streakText.ForegroundColor = _consecutiveLosses > 0 ? Color.Orange : Color.Silver;
// Status Update
if (_isDailyLockout)
{
_statusText.Text = "MAX DD LOCK";
_statusText.ForegroundColor = Color.Red;
}
else if (_consecutiveLosses >= MaxConsecutiveLosses)
{
_statusText.Text = "STREAK LOCK";
_statusText.ForegroundColor = Color.Red;
}
else if (IsCooldownActive())
{
int remainingMins = RevengeCooldownMins - (int)(Server.Time - _lastLossTime).TotalMinutes;
_statusText.Text = $"COOLDOWN ({remainingMins}m)";
_statusText.ForegroundColor = Color.Orange;
}
else
{
_statusText.Text = "ACTIVE";
_statusText.ForegroundColor = Color.Teal;
}
// Allow live toggling of Stress Protocol via cBot parameters during runtime
_stressText.Text = StressMode ? "ENGAGED" : "STANDBY";
_stressText.ForegroundColor = StressMode ? Color.MediumPurple : Color.Gray;
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: July psychology scorecard: tilt days and wins
Key Differences & Architectural Advantages
OnPositionClosed Event: Pine Script has to parse historical trade arrays on bar close to detect a loss. In cAlgo, Positions.Closed += OnPositionClosed hooks directly into the broker feed, triggering the cooldown counter the exact millisecond the stop loss is hit.
True Real-Time Flattening: Because OnTick() processes every individual price update, a trade that dips your equity below the MaxDailyDrawdownPct limit is closed instantly mid-candle via FlattenAllPositions(), completely eliminating slippage gaps caused by waiting for bar closures.
UI Render Loop: The InitializeUI() and UpdateUI() functions map directly to WPF-style StackPanels and TextBlocks (which cTrader is built on). It gives you a clean, tear-free overlay that won't obscure raw price action or clutter your 1-minute structure zones.
OnPositionClosed Event: Pine Script has to parse historical trade arrays on bar close to detect a loss. In cAlgo, Positions.Closed += OnPositionClosed hooks directly into the broker feed, triggering the cooldown counter the exact millisecond the stop loss is hit.
True Real-Time Flattening: Because OnTick() processes every individual price update, a trade that dips your equity below the MaxDailyDrawdownPct limit is closed instantly mid-candle via FlattenAllPositions(), completely eliminating slippage gaps caused by waiting for bar closures.
UI Render Loop: The InitializeUI() and UpdateUI() functions map directly to WPF-style StackPanels and TextBlocks (which cTrader is built on). It gives you a clean, tear-free overlay that won't obscure raw price action or clutter your 1-minute structure zones.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: July psychology scorecard: tilt days and wins
Because MetaTrader bridges the gap between C# object-oriented paradigms and legacy procedural execution, the implementation splits into two distinct architectures.
MT5 allows us to replicate the event-driven accuracy of the cTrader OnPositionClosed hook using the OnTradeTransaction handler. MT4 lacks this event model, forcing us to poll the history pool procedurally inside the OnTick() loop.
Here is the complete professional framework for both platforms.
MT5 allows us to replicate the event-driven accuracy of the cTrader OnPositionClosed hook using the OnTradeTransaction handler. MT4 lacks this event model, forcing us to poll the history pool procedurally inside the OnTick() loop.
Here is the complete professional framework for both platforms.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: July psychology scorecard: tilt days and wins
1. The MT5 (MQL5) Implementation
This utilizes CTrade for execution and OnTradeTransaction for asynchronous, millisecond-accurate loss detection—identical to the C# event-driven model.
This utilizes CTrade for execution and OnTradeTransaction for asynchronous, millisecond-accurate loss detection—identical to the C# event-driven model.
Code: Select all
//+------------------------------------------------------------------+
//| ProDisciplineFramework_MT5.mq5|
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
input string grpRisk = "--- Risk Parameters ---";
input double MaxDailyDrawdownPct = 2.0; // Max Daily Drawdown (%)
input int MaxConsecutiveLosses = 3; // Max Consecutive Losses
input int RevengeCooldownMins = 10; // Post-Loss Cooldown (Mins)
input string grpStress = "--- Stress Protocol ---";
input bool StressMode = false; // Engage Stress Protocol
input double StressExposurePct = 25.0; // Stress Sizing Exposure (%)
input double BaseRiskPct = 1.0; // Base Risk Per Trade (%)
// State variables
double startOfDayEquity;
datetime currentSessionDate;
bool isDailyLockout;
int consecutiveLosses;
datetime lastLossTime;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
currentSessionDate = GetCurrentDay();
startOfDayEquity = AccountInfoDouble(ACCOUNT_EQUITY);
isDailyLockout = false;
consecutiveLosses = 0;
InitializeUI();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
CheckSessionRollover();
EnforceDailyDrawdown();
UpdateUI();
if(CanTrade())
{
// Placeholder PA setup (e.g., engulfing)
double close1 = iClose(_Symbol, PERIOD_CURRENT, 1);
double open1 = iOpen(_Symbol, PERIOD_CURRENT, 1);
double close2 = iClose(_Symbol, PERIOD_CURRENT, 2);
double open2 = iOpen(_Symbol, PERIOD_CURRENT, 2);
bool goLong = close1 > open1 && close2 < open2;
bool goShort = close1 < open1 && close2 > open2;
if(goLong && !PositionSelect(_Symbol))
trade.Buy(GetCalculatedVolume(), _Symbol);
else if(goShort && !PositionSelect(_Symbol))
trade.Sell(GetCalculatedVolume(), _Symbol);
}
}
//+------------------------------------------------------------------+
//| Trade Transaction Event (Replaces MT4 History Polling) |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
{
// Catch deals exactly when they hit the history pool
if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
{
HistorySelect(0, TimeCurrent());
ulong ticket = trans.deal;
if(HistoryDealSelect(ticket))
{
if(HistoryDealGetString(ticket, DEAL_SYMBOL) == _Symbol)
{
double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT) + HistoryDealGetDouble(ticket, DEAL_COMMISSION) + HistoryDealGetDouble(ticket, DEAL_SWAP);
if(profit < 0)
{
lastLossTime = TimeCurrent();
consecutiveLosses++;
}
else if(profit > 0)
{
consecutiveLosses = 0; // Reset streak on win
}
}
}
}
}
//+------------------------------------------------------------------+
//| Core Risk Logic |
//+------------------------------------------------------------------+
void CheckSessionRollover()
{
datetime today = GetCurrentDay();
if(today != currentSessionDate)
{
currentSessionDate = today;
startOfDayEquity = AccountInfoDouble(ACCOUNT_EQUITY);
isDailyLockout = false;
consecutiveLosses = 0;
Print("New trading session started. Risk parameters reset.");
}
}
void EnforceDailyDrawdown()
{
if(isDailyLockout) return;
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
double drawdownPct = ((startOfDayEquity - currentEquity) / startOfDayEquity) * 100.0;
if(drawdownPct >= MaxDailyDrawdownPct)
{
isDailyLockout = true;
FlattenAllPositions();
Print("CIRCUIT BREAKER: Max Daily Drawdown breached. Flattening.");
}
}
void FlattenAllPositions()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == _Symbol)
{
trade.PositionClose(ticket);
}
}
}
bool CanTrade()
{
if(isDailyLockout) return false;
if(consecutiveLosses >= MaxConsecutiveLosses) return false;
if(lastLossTime > 0 && (TimeCurrent() - lastLossTime) < (RevengeCooldownMins * 60)) return false;
return true;
}
double GetCalculatedVolume()
{
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double riskAmount = equity * (BaseRiskPct / 100.0);
if(StressMode) riskAmount *= (StressExposurePct / 100.0);
// Convert risk amount to lots (standardizing against contract size)
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double lots = riskAmount / (100 * tickValue); // Example math for generic 100 pip SL
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
return MathMax(minLot, MathRound(lots / stepLot) * stepLot);
}
datetime GetCurrentDay()
{
MqlDateTime dt;
TimeCurrent(dt);
dt.hour = 0; dt.min = 0; dt.sec = 0;
return StructToTime(dt);
}
//+------------------------------------------------------------------+
//| UI Generation |
//+------------------------------------------------------------------+
void InitializeUI()
{
ObjectCreate(0, "HUD_BG", OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, "HUD_BG", OBJPROP_CORNER, CORNER_RIGHT_LOWER);
ObjectSetInteger(0, "HUD_BG", OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, "HUD_BG", OBJPROP_YDISTANCE, 10);
ObjectSetInteger(0, "HUD_BG", OBJPROP_XSIZE, 200);
ObjectSetInteger(0, "HUD_BG", OBJPROP_YSIZE, 100);
ObjectSetInteger(0, "HUD_BG", OBJPROP_BGCOLOR, clrBlack);
CreateLabel("HUD_TITLE", "SYSTEM STATUS:", 20, 80, clrGray);
CreateLabel("HUD_STATUS", "ACTIVE", 120, 80, clrTeal);
CreateLabel("HUD_DD_TXT", "DD %:", 20, 60, clrGray);
CreateLabel("HUD_DD_VAL", "0.00%", 120, 60, clrSilver);
CreateLabel("HUD_STREAK_TXT", "STREAK:", 20, 40, clrGray);
CreateLabel("HUD_STREAK_VAL", "0 Loss", 120, 40, clrSilver);
CreateLabel("HUD_STRESS_TXT", "STRESS MODE:", 20, 20, clrGray);
CreateLabel("HUD_STRESS_VAL", StressMode ? "ENGAGED" : "STANDBY", 120, 20, StressMode ? clrMediumPurple : clrGray);
}
void CreateLabel(string name, string text, int x, int y, color clr)
{
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetString(0, name, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 8);
}
void UpdateUI()
{
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double ddPct = MathMax(0.0, ((startOfDayEquity - equity) / startOfDayEquity) * 100.0);
ObjectSetString(0, "HUD_DD_VAL", OBJPROP_TEXT, DoubleToString(ddPct, 2) + "% / " + DoubleToString(MaxDailyDrawdownPct, 1) + "%");
ObjectSetInteger(0, "HUD_DD_VAL", OBJPROP_COLOR, ddPct > (MaxDailyDrawdownPct * 0.8) ? clrOrange : clrSilver);
ObjectSetString(0, "HUD_STREAK_VAL", OBJPROP_TEXT, IntegerToString(consecutiveLosses) + " Loss");
ObjectSetInteger(0, "HUD_STREAK_VAL", OBJPROP_COLOR, consecutiveLosses > 0 ? clrOrange : clrSilver);
if(isDailyLockout)
{
ObjectSetString(0, "HUD_STATUS", OBJPROP_TEXT, "MAX DD LOCK");
ObjectSetInteger(0, "HUD_STATUS", OBJPROP_COLOR, clrRed);
}
else if(consecutiveLosses >= MaxConsecutiveLosses)
{
ObjectSetString(0, "HUD_STATUS", OBJPROP_TEXT, "STREAK LOCK");
ObjectSetInteger(0, "HUD_STATUS", OBJPROP_COLOR, clrRed);
}
else if(lastLossTime > 0 && (TimeCurrent() - lastLossTime) < (RevengeCooldownMins * 60))
{
int remainingMins = RevengeCooldownMins - (int)((TimeCurrent() - lastLossTime) / 60);
ObjectSetString(0, "HUD_STATUS", OBJPROP_TEXT, "COOLDOWN (" + IntegerToString(remainingMins) + "m)");
ObjectSetInteger(0, "HUD_STATUS", OBJPROP_COLOR, clrOrange);
}
else
{
ObjectSetString(0, "HUD_STATUS", OBJPROP_TEXT, "ACTIVE");
ObjectSetInteger(0, "HUD_STATUS", OBJPROP_COLOR, clrTeal);
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: July psychology scorecard: tilt days and wins
2. The MT4 (MQL4) Core Differences
Because MT4 operates on a legacy procedural history pool without transaction event hooks, the OnTradeTransaction function from MT5 must be replaced with an active polling mechanism inside OnTick().
To port the above script to MT4, you substitute the execution engine (OrderSend instead of CTrade) and add this history-tracking module to detect the closed trades:
Because MT4 operates on a legacy procedural history pool without transaction event hooks, the OnTradeTransaction function from MT5 must be replaced with an active polling mechanism inside OnTick().
To port the above script to MT4, you substitute the execution engine (OrderSend instead of CTrade) and add this history-tracking module to detect the closed trades:
Code: Select all
// Required MT4 global state tracking
int lastHistoryTotal = 0;
void OnTick()
{
CheckSessionRollover();
CheckClosedTradesMT4(); // MT4 Polling mechanism
EnforceDailyDrawdown();
UpdateUI();
// ... execution logic using OrderSend()
}
//+------------------------------------------------------------------+
//| MT4 Procedural History Polling |
//+------------------------------------------------------------------+
void CheckClosedTradesMT4()
{
int currentHistory = OrdersHistoryTotal();
// Only parse the loop if the history pool has increased
if(currentHistory > lastHistoryTotal)
{
for(int i = currentHistory - 1; i >= lastHistoryTotal; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == 12345) // Assume your EA magic number
{
double profit = OrderProfit() + OrderSwap() + OrderCommission();
if(profit < 0)
{
lastLossTime = TimeCurrent();
consecutiveLosses++;
}
else if(profit > 0)
{
consecutiveLosses = 0; // Reset streak
}
}
}
}
lastHistoryTotal = currentHistory; // Update state tracker
}
}
//+------------------------------------------------------------------+
//| MT4 Flatten Positions Logic |
//+------------------------------------------------------------------+
void FlattenAllPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol())
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrRed);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrRed);
}
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: July psychology scorecard: tilt days and wins
By explicitly mapping lastHistoryTotal, you avoid looping through thousands of historical trades on a 1-minute chart during every tick, maintaining execution speed while still catching the exact second your order rejection or stop-loss hits the ledger.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.