System Win/Loss Streak Probability Engine
Posted: Thu Aug 06, 2026 10:00 pm
Good evening scalpers,
today i decided to share with you another of my indicator, which i use time to time:
Instead of guessing random market directions, this indicator uses Markov chain-style probability based on your actual trading system's performance. It scans your closed trades, tallies the historical frequency of consecutive wins and losses, and calculates the statistical probability of your current streak continuing or reversing on the very next trade.
I've structured this with clean, event-driven C-style logic and included your business and trading channel branding in the dashboard UI.
For MT4 in MQL4:
today i decided to share with you another of my indicator, which i use time to time:
Instead of guessing random market directions, this indicator uses Markov chain-style probability based on your actual trading system's performance. It scans your closed trades, tallies the historical frequency of consecutive wins and losses, and calculates the statistical probability of your current streak continuing or reversing on the very next trade.
I've structured this with clean, event-driven C-style logic and included your business and trading channel branding in the dashboard UI.
For MT4 in MQL4:
Code: Select all
//+------------------------------------------------------------------+
//| SystemStreakProbabilityEngine.mq4 |
//| Created for Pavel Tuček |
//| aiprofisolutions.com |
//+------------------------------------------------------------------+
#property copyright "Pavel Tuček | AI Profi Solutions"
#property link "https://aiprofisolutions.com"
#property version "1.00"
#property strict
#property indicator_chart_window
//--- Input Parameters
input string InpSymbolFilter = ""; // Filter by Symbol (Empty = All)
input int InpMagicNumber = 0; // Filter by Magic Number (0 = All)
input int InpHistoryDays = 0; // History Days to Analyze (0 = All Time)
input color InpHeaderColor = clrWhite; // Header Text Color
input color InpDataColor = clrSilver; // Data Text Color
input int InpCorner = 0; // Dashboard Corner (0=TopLeft)
//--- Global Variables
string prefix = "StreakEngine_";
int totalTrades = 0;
int totalWins = 0;
int totalLosses = 0;
int currentStreak = 0;
bool isWinStreak = false;
int winStreaks[];
int lossStreaks[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
ArrayResize(winStreaks, 100);
ArrayResize(lossStreaks, 100);
// Initial Calculation
CalculateStreaks();
DrawDashboard();
// Set a timer to refresh the dashboard every 10 seconds
// This avoids heavy CPU usage on every tick
EventSetTimer(10);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
ObjectsDeleteAll(0, prefix);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// Relies on OnTimer for trade history updates to save CPU
return(rates_total);
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
CalculateStreaks();
DrawDashboard();
}
//+------------------------------------------------------------------+
//| Core Logic: Calculate Streaks from Account History |
//+------------------------------------------------------------------+
void CalculateStreaks()
{
totalTrades = 0;
totalWins = 0;
totalLosses = 0;
ArrayInitialize(winStreaks, 0);
ArrayInitialize(lossStreaks, 0);
int currentRun = 0;
bool lastWasWin = false;
bool firstTrade = true;
currentStreak = 0;
datetime fromTime = 0;
if(InpHistoryDays > 0)
fromTime = TimeCurrent() - (InpHistoryDays * 24 * 60 * 60);
int ordersTotal = OrdersHistoryTotal();
// Read history from oldest to newest
for(int i = 0; i < ordersTotal; i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
// Skip non-trading operations (deposits, withdrawals, cancelled limits)
if(OrderType() > OP_SELL) continue;
// Apply Filters
if(InpMagicNumber > 0 && OrderMagicNumber() != InpMagicNumber) continue;
if(StringLen(InpSymbolFilter) > 0 && OrderSymbol() != InpSymbolFilter) continue;
if(OrderCloseTime() < fromTime) continue;
double profit = OrderProfit() + OrderCommission() + OrderSwap();
bool isWin = (profit > 0);
totalTrades++;
if(isWin) totalWins++;
else totalLosses++;
if(firstTrade)
{
lastWasWin = isWin;
currentRun = 1;
firstTrade = false;
}
else
{
if(isWin == lastWasWin)
{
currentRun++;
}
else
{
// Streak broken, record the completed streak
if(lastWasWin)
{
if(currentRun < ArraySize(winStreaks)) winStreaks[currentRun]++;
}
else
{
if(currentRun < ArraySize(lossStreaks)) lossStreaks[currentRun]++;
}
// Reset for the new streak direction
lastWasWin = isWin;
currentRun = 1;
}
}
}
}
// Capture the state of the currently active streak
if(totalTrades > 0)
{
currentStreak = currentRun;
isWinStreak = lastWasWin;
}
}
//+------------------------------------------------------------------+
//| Dashboard Rendering |
//+------------------------------------------------------------------+
void DrawDashboard()
{
ObjectsDeleteAll(0, prefix); // Clear previous UI
int x = 25;
int y = 25;
int yStep = 22;
double winRate = (totalTrades > 0) ? ((double)totalWins / totalTrades) * 100.0 : 0.0;
// UI Headers
CreateLabel("title", "System Win/Loss Streak Probability Engine", x, y, InpHeaderColor, 12, true); y += yStep * 2;
// Trade Stats
CreateLabel("stats", StringFormat("Analyzed Trades: %d (W: %d | L: %d)", totalTrades, totalWins, totalLosses), x, y, InpDataColor); y += yStep;
CreateLabel("winrate", StringFormat("System Win Rate: %.2f%%", winRate), x, y, InpDataColor); y += yStep * 2;
// Current Streak Info
string streakText = isWinStreak ? "WINS" : "LOSSES";
color streakColor = isWinStreak ? clrLimeGreen : clrTomato;
CreateLabel("current", StringFormat("Active Streak: %d %s", currentStreak, streakText), x, y, streakColor, 11, true); y += yStep * 2;
// Probability Math
double probContinue = 0.0;
int totalReachedCurrent = 0;
int totalSurpassedCurrent = 0;
if(isWinStreak && currentStreak > 0)
{
for(int i = currentStreak; i < ArraySize(winStreaks); i++)
{
totalReachedCurrent += winStreaks[i];
if(i > currentStreak) totalSurpassedCurrent += winStreaks[i];
}
}
else if(!isWinStreak && currentStreak > 0)
{
for(int i = currentStreak; i < ArraySize(lossStreaks); i++)
{
totalReachedCurrent += lossStreaks[i];
if(i > currentStreak) totalSurpassedCurrent += lossStreaks[i];
}
}
if(totalReachedCurrent > 0)
probContinue = ((double)totalSurpassedCurrent / totalReachedCurrent) * 100.0;
double probReverse = (totalReachedCurrent > 0) ? 100.0 - probContinue : 0.0;
string actionText = isWinStreak ? "LOSS (Reversal)" : "WIN (Reversal)";
color reverseColor = isWinStreak ? clrTomato : clrLimeGreen;
CreateLabel("prob1", StringFormat("Prob. of extending to %d %s: %.2f%%", currentStreak + 1, streakText, probContinue), x, y, clrGold); y += yStep;
CreateLabel("prob2", StringFormat("Prob. of next trade being a %s: %.2f%%", actionText, probReverse), x, y, reverseColor, 10, true); y += yStep * 2;
// Footer
CreateLabel("footer", "Forex, Stocks & Me | AI Profi Solutions", x, y, clrDimGray, 8);
}
//+------------------------------------------------------------------+
//| Helper: Create Text Label |
//+------------------------------------------------------------------+
void CreateLabel(string nameSuffix, string text, int x, int y, color clr, int size=10, bool bold=false)
{
string objName = prefix + nameSuffix;
if(ObjectFind(0, objName) < 0) ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, objName, OBJPROP_CORNER, InpCorner);
ObjectSetString(0, objName, OBJPROP_TEXT, text);
ObjectSetString(0, objName, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, size);
ObjectSetInteger(0, objName, OBJPROP_COLOR, clr);
ObjectSetInteger(0, objName, OBJPROP_BACK, false);
ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
}
//+------------------------------------------------------------------+