The 1% Rule Isn't Optional
Re: The 1% Rule Isn't Optional
This is known as Anti-Martingale scaling. You are mathematically forced to risk less when you are cold, and risk more when you are hot. This geometric compounding is the only mathematical mechanism that allows a small trading account to achieve exponential growth over a large sample size.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
The Kelly Criterion is the mathematical formula that determines the exact position size required to achieve the absolute maximum compound growth rate for a strategy. It finds the "apex" of the risk curve—the exact percentage where risking a penny more mathematically decreases your long-term returns.
Originally developed by John L. Kelly Jr. in 1956 at Bell Labs to analyze signal noise, it was quickly adapted by mathematicians (like Edward Thorp) to beat the blackjack tables in Las Vegas, and eventually, the financial markets.
The Kelly Formula
To find your optimal risk, the formula isolates your edge by combining your win probability and your payout ratio:
K% = W - \left( \frac{1 - W}{R} \right)
K = The Kelly Percentage (the optimal fraction of your account to risk)
W = Win Rate (expressed as a decimal, e.g., 0.50 for 50%)
R = Reward-to-Risk Ratio (Average Winning Trade / Average Losing Trade)
Originally developed by John L. Kelly Jr. in 1956 at Bell Labs to analyze signal noise, it was quickly adapted by mathematicians (like Edward Thorp) to beat the blackjack tables in Las Vegas, and eventually, the financial markets.
The Kelly Formula
To find your optimal risk, the formula isolates your edge by combining your win probability and your payout ratio:
K% = W - \left( \frac{1 - W}{R} \right)
K = The Kelly Percentage (the optimal fraction of your account to risk)
W = Win Rate (expressed as a decimal, e.g., 0.50 for 50%)
R = Reward-to-Risk Ratio (Average Winning Trade / Average Losing Trade)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
A Scalping Example:
If your strategy has a 50% win rate ($W = 0.5$) and your average winner is twice the size of your average loser ($R = 2$):
K% = 0.5 - \left( \frac{1 - 0.5}{2} \right) = 0.5 - 0.25 = 0.25
The Kelly Criterion dictates you should risk exactly 25% of your account equity per trade to grow your account as fast as mathematically possible.
The "Kelly Curve" and the Danger of Over-Sizing
The genius of Kelly isn't just finding the maximum growth rate; it's proving that more risk eventually equals less profit.
Geometric growth operates on a parabola.
Under-Kelly: If you risk less than 25%, you leave money on the table, but your equity curve is smooth and drawdowns are shallow.
Full Kelly (The Apex): If you risk exactly 25%, you achieve the highest theoretical growth.
Over-Kelly (The Death Zone): If you risk more than 25% (say, 45%), the compounding math inverts. The heavy drawdowns from your losing trades now mathematically outweigh your winning trades. Your strategy will eventually bleed to zero, even though the strategy itself has a profitable edge.
If your strategy has a 50% win rate ($W = 0.5$) and your average winner is twice the size of your average loser ($R = 2$):
K% = 0.5 - \left( \frac{1 - 0.5}{2} \right) = 0.5 - 0.25 = 0.25
The Kelly Criterion dictates you should risk exactly 25% of your account equity per trade to grow your account as fast as mathematically possible.
The "Kelly Curve" and the Danger of Over-Sizing
The genius of Kelly isn't just finding the maximum growth rate; it's proving that more risk eventually equals less profit.
Geometric growth operates on a parabola.
Under-Kelly: If you risk less than 25%, you leave money on the table, but your equity curve is smooth and drawdowns are shallow.
Full Kelly (The Apex): If you risk exactly 25%, you achieve the highest theoretical growth.
Over-Kelly (The Death Zone): If you risk more than 25% (say, 45%), the compounding math inverts. The heavy drawdowns from your losing trades now mathematically outweigh your winning trades. Your strategy will eventually bleed to zero, even though the strategy itself has a profitable edge.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
Why Professionals Use "Fractional Kelly"
In the real world, almost no professional trader sizes at "Full Kelly." They universally trade at Half-Kelly or even Quarter-Kelly. There are two reasons for this:
Estimation Risk: In a casino, the math of a blackjack deck is absolute. In financial markets, your Win Rate and Reward/Risk ratio are just historical estimates. If you calculate Kelly based on a 50% win rate, size at Full Kelly, but market conditions change and your win rate drops to 40%, you are instantly operating in the "Over-Kelly" death zone.
Psychological Ruin: A Full Kelly sizing model mathematically expects peak-to-trough drawdowns of 80% to 90% at some point in its life cycle. Very few humans can psychologically withstand a 90% drawdown without abandoning the strategy entirely. Half-Kelly provides 75% of the theoretical maximum growth, but cuts the expected drawdowns in half.
By sizing at a small fraction of Kelly (which usually aligns closely with the standard 1-2% risk rule), you ensure that even when your edge compresses, you are still operating safely on the left side of the optimal growth curve.
In the real world, almost no professional trader sizes at "Full Kelly." They universally trade at Half-Kelly or even Quarter-Kelly. There are two reasons for this:
Estimation Risk: In a casino, the math of a blackjack deck is absolute. In financial markets, your Win Rate and Reward/Risk ratio are just historical estimates. If you calculate Kelly based on a 50% win rate, size at Full Kelly, but market conditions change and your win rate drops to 40%, you are instantly operating in the "Over-Kelly" death zone.
Psychological Ruin: A Full Kelly sizing model mathematically expects peak-to-trough drawdowns of 80% to 90% at some point in its life cycle. Very few humans can psychologically withstand a 90% drawdown without abandoning the strategy entirely. Half-Kelly provides 75% of the theoretical maximum growth, but cuts the expected drawdowns in half.
By sizing at a small fraction of Kelly (which usually aligns closely with the standard 1-2% risk rule), you ensure that even when your edge compresses, you are still operating safely on the left side of the optimal growth curve.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
This Pine Script v5 implementation calculates your optimal Kelly percentage based on your historical edge, applies a professional fractional modifier (e.g., Half-Kelly), and automatically sizes the trade based on dynamic account equity and stop-loss distance.
It uses a simple moving average crossover as a placeholder entry trigger so you can visualize the sizing math in the backtester.
It uses a simple moving average crossover as a placeholder entry trigger so you can visualize the sizing math in the backtester.
Code: Select all
//@version=5
strategy("Fractional Kelly Position Sizer", overlay=true, initial_capital=10000, default_qty_type=strategy.cash)
// =========================================================================
// 1. STRATEGY EDGE INPUTS (Calculate your Kelly)
// =========================================================================
i_winRate = input.float(50.0, title="Historical Win Rate (%)", minval=1.0, maxval=99.0, group="Kelly Parameters") / 100.0
i_rr = input.float(2.0, title="Historical Reward/Risk Ratio", minval=0.1, group="Kelly Parameters")
i_fraction = input.float(0.5, title="Kelly Fraction (0.5 = Half Kelly)", minval=0.1, maxval=1.0, step=0.1, group="Kelly Parameters")
// =========================================================================
// 2. STOP LOSS INPUTS (Determine Market Structure)
// =========================================================================
i_atrLen = input.int(14, title="ATR Length for Stop", group="Risk Management")
i_atrMult = input.float(1.5, title="ATR Multiplier for Stop Distance", group="Risk Management")
// =========================================================================
// 3. THE KELLY & POSITION SIZING MATH
// =========================================================================
// Full Kelly Formula: W - ((1 - W) / R)
fullKelly = i_winRate - ((1.0 - i_winRate) / i_rr)
// Apply fractional safety brake (and prevent negative risk if edge is mathematically negative)
appliedRisk = math.max(0, fullKelly * i_fraction)
// Calculate dynamic risk amount based on current account equity
riskAmount = strategy.equity * appliedRisk
// Calculate stop distance in fiat terms
atr = ta.atr(i_atrLen)
stopDist = atr * i_atrMult
// Final position size: Risk Amount / Distance to Stop
// (This fulfills the rule: Market dictates stop, risk rules dictate size)
positionSize = stopDist > 0 ? (riskAmount / stopDist) : 0
// =========================================================================
// 4. DUMMY ENTRY LOGIC (Replace with your price action trigger)
// =========================================================================
fastSma = ta.sma(close, 10)
slowSma = ta.sma(close, 20)
longTrigger = ta.crossover(fastSma, slowSma)
shortTrigger = ta.crossunder(fastSma, slowSma)
// =========================================================================
// 5. EXECUTION
// =========================================================================
if longTrigger and strategy.opentrades == 0 and appliedRisk > 0
strategy.entry("Long", strategy.long, qty=positionSize)
strategy.exit("Exit Long", "Long", stop=close - stopDist, limit=close + (stopDist * i_rr))
if shortTrigger and strategy.opentrades == 0 and appliedRisk > 0
strategy.entry("Short", strategy.short, qty=positionSize)
strategy.exit("Exit Short", "Short", stop=close + stopDist, limit=close - (stopDist * i_rr))
// =========================================================================
// 6. DASHBOARD UI
// =========================================================================
var table infoTable = table.new(position.top_right, 2, 3, border_width=1, border_color=color.gray, frame_color=color.black, frame_width=1)
if barstate.islast
table.cell(infoTable, 0, 0, "Full Kelly %", text_color=color.white, bgcolor=color.new(color.blue, 80))
table.cell(infoTable, 1, 0, str.tostring(fullKelly * 100, "#.##") + "%", text_color=color.white, bgcolor=color.new(color.blue, 80))
table.cell(infoTable, 0, 1, "Applied Fractional Risk", text_color=color.white, bgcolor=color.new(color.teal, 80))
table.cell(infoTable, 1, 1, str.tostring(appliedRisk * 100, "#.##") + "%", text_color=color.white, bgcolor=color.new(color.teal, 80))
table.cell(infoTable, 0, 2, "Current Risk ($)", text_color=color.white, bgcolor=color.new(color.red, 80))
table.cell(infoTable, 1, 2, "$" + str.tostring(riskAmount, "#.##"), text_color=color.white, bgcolor=color.new(color.red, 80))Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
Script Mechanics
strategy.equity: The script dynamically references your closed equity plus unrealized P&L. If you hit a losing streak, strategy.equity drops, your riskAmount strictly decreases, and the asymptotic brake applies.
positionSize = riskAmount / stopDist: This line forces the discipline we discussed. The ATR calculates where the chart structure proves the trade wrong, and only then is the position size populated to risk exactly your applied fractional Kelly percentage.
The Zero-Bound Check (math.max(0, ...)): If you plug in a Win Rate and Reward/Risk ratio that has a negative mathematical expectancy, the Kelly formula will return a negative number. The script automatically sets your risk to 0% and blocks all entries, preventing you from mathematically guaranteeing the ruin of the account.
strategy.equity: The script dynamically references your closed equity plus unrealized P&L. If you hit a losing streak, strategy.equity drops, your riskAmount strictly decreases, and the asymptotic brake applies.
positionSize = riskAmount / stopDist: This line forces the discipline we discussed. The ATR calculates where the chart structure proves the trade wrong, and only then is the position size populated to risk exactly your applied fractional Kelly percentage.
The Zero-Bound Check (math.max(0, ...)): If you plug in a Win Rate and Reward/Risk ratio that has a negative mathematical expectancy, the Kelly formula will return a negative number. The script automatically sets your risk to 0% and blocks all entries, preventing you from mathematically guaranteeing the ruin of the account.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
Upgrading to a "Rolling Kelly" is the exact mechanism quantitative funds use to adapt to market regimes. By calculating your edge dynamically over a rolling window, the algorithm automatically throttles up your risk when your strategy gets "hot" and chokes your position size to near-zero when the strategy breaks down.
To do this in Pine Script v5, we use the strategy.closedtrades array to loop through your historical performance and continuously recalculate your Win Rate and Reward/Risk (R/R) ratio on every bar.
Here is the upgraded Dynamic Fractional Kelly script.
To do this in Pine Script v5, we use the strategy.closedtrades array to loop through your historical performance and continuously recalculate your Win Rate and Reward/Risk (R/R) ratio on every bar.
Here is the upgraded Dynamic Fractional Kelly script.
Code: Select all
//@version=5
strategy("Dynamic Rolling Kelly Position Sizer", overlay=true, initial_capital=10000, default_qty_type=strategy.cash)
// =========================================================================
// 1. BOOTSTRAP INPUTS (Used until we have enough trade history)
// =========================================================================
i_initialWinRate = input.float(50.0, title="Bootstrap Win Rate (%)", minval=1.0, maxval=99.0, group="Kelly Parameters") / 100.0
i_initialRR = input.float(2.0, title="Bootstrap Reward/Risk", minval=0.1, group="Kelly Parameters")
i_fraction = input.float(0.5, title="Kelly Fraction (0.5 = Half Kelly)", minval=0.1, maxval=1.0, step=0.1, group="Kelly Parameters")
i_lookback = input.int(100, title="Rolling Trade Window", minval=10, maxval=500, group="Kelly Parameters")
// =========================================================================
// 2. STOP LOSS INPUTS
// =========================================================================
i_atrLen = input.int(14, title="ATR Length for Stop", group="Risk Management")
i_atrMult = input.float(1.5, title="ATR Multiplier for Stop Distance", group="Risk Management")
// =========================================================================
// 3. DYNAMIC EDGE CALCULATION (The Rolling Window)
// =========================================================================
var float dynWinRate = i_initialWinRate
var float dynRR = i_initialRR
int totalTrades = strategy.closedtrades
// Only run the loop if trades exist
if totalTrades > 0
int wins = 0
float grossProfit = 0.0
float grossLoss = 0.0
int winCount = 0
int lossCount = 0
// Determine starting index for the rolling window
int startIdx = math.max(0, totalTrades - i_lookback)
int tradesToAnalyze = totalTrades - startIdx
if tradesToAnalyze > 0
for i = startIdx to totalTrades - 1
float profit = strategy.closedtrades.profit(i)
if profit > 0
wins += 1
grossProfit += profit
winCount += 1
else if profit < 0
grossLoss += math.abs(profit)
lossCount += 1
// Calculate Dynamic Win Rate
dynWinRate := wins / tradesToAnalyze
// Calculate Dynamic Reward/Risk
float avgWin = winCount > 0 ? grossProfit / winCount : 0.0
float avgLoss = lossCount > 0 ? grossLoss / lossCount : 0.0
// Prevent division by zero if there are no losses yet
dynRR := avgLoss > 0 ? avgWin / avgLoss : i_initialRR
// =========================================================================
// 4. THE KELLY & POSITION SIZING MATH
// =========================================================================
// Use dynamic variables instead of static inputs
fullKelly = dynWinRate - ((1.0 - dynWinRate) / dynRR)
// Apply fractional safety brake (bounds strictly to 0 if edge is negative)
appliedRisk = math.max(0, fullKelly * i_fraction)
riskAmount = strategy.equity * appliedRisk
// Calculate stop distance in fiat terms
atr = ta.atr(i_atrLen)
stopDist = atr * i_atrMult
positionSize = stopDist > 0 ? (riskAmount / stopDist) : 0
// =========================================================================
// 5. DUMMY ENTRY LOGIC (Replace with your price action trigger)
// =========================================================================
fastSma = ta.sma(close, 10)
slowSma = ta.sma(close, 20)
longTrigger = ta.crossover(fastSma, slowSma)
shortTrigger = ta.crossunder(fastSma, slowSma)
// =========================================================================
// 6. EXECUTION
// =========================================================================
if longTrigger and strategy.opentrades == 0 and appliedRisk > 0
strategy.entry("Long", strategy.long, qty=positionSize)
strategy.exit("Exit Long", "Long", stop=close - stopDist, limit=close + (stopDist * dynRR)) // Using dynRR for limit target
if shortTrigger and strategy.opentrades == 0 and appliedRisk > 0
strategy.entry("Short", strategy.short, qty=positionSize)
strategy.exit("Exit Short", "Short", stop=close + stopDist, limit=close - (stopDist * dynRR))
// =========================================================================
// 7. DASHBOARD UI
// =========================================================================
var table infoTable = table.new(position.top_right, 2, 5, border_width=1, border_color=color.gray, frame_color=color.black, frame_width=1)
if barstate.islast
table.cell(infoTable, 0, 0, "Rolling Win Rate", text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 1, 0, str.tostring(dynWinRate * 100, "#.##") + "%", text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 0, 1, "Rolling R/R", text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 1, 1, str.tostring(dynRR, "#.##"), text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 0, 2, "Full Kelly %", text_color=color.white, bgcolor=color.new(color.blue, 20))
table.cell(infoTable, 1, 2, str.tostring(fullKelly * 100, "#.##") + "%", text_color=color.white, bgcolor=color.new(color.blue, 20))
table.cell(infoTable, 0, 3, "Applied Fractional Risk", text_color=color.white, bgcolor=color.new(color.teal, 20))
table.cell(infoTable, 1, 3, str.tostring(appliedRisk * 100, "#.##") + "%", text_color=color.white, bgcolor=color.new(color.teal, 20))
table.cell(infoTable, 0, 4, "Current Risk ($)", text_color=color.white, bgcolor=color.new(color.red, 20))
table.cell(infoTable, 1, 4, "$" + str.tostring(riskAmount, "#.##"), text_color=color.white, bgcolor=color.new(color.red, 20))Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
The New Mechanics
The Bootstrap Phase: Because you have a 0% Win Rate on trade #1, the algorithm uses the "Bootstrap" inputs to generate your initial Kelly size. Once your first trade closes, it dynamically takes over.
The Rolling for Loop: The script now features an array loop for i = startIdx to totalTrades - 1. Every time a bar prints, it grabs up to the last 100 completed trades using strategy.closedtrades.profit(i) and manually tallies your gross profit versus gross loss.
The Safety Bounds Check: If your strategy hasn't taken any losses yet (e.g., you are 5-0 to start), dividing average profit by average loss would trigger a Divide By Zero error. The script prevents this by defaulting dynRR to your bootstrap value until your first losing trade registers.
Dynamic Profit Targets: Note in the Execution section, your limit exit is now also scaling dynamically via limit=close + (stopDist * dynRR). If your historical R/R improves, your future limit orders will automatically stretch further.
The Bootstrap Phase: Because you have a 0% Win Rate on trade #1, the algorithm uses the "Bootstrap" inputs to generate your initial Kelly size. Once your first trade closes, it dynamically takes over.
The Rolling for Loop: The script now features an array loop for i = startIdx to totalTrades - 1. Every time a bar prints, it grabs up to the last 100 completed trades using strategy.closedtrades.profit(i) and manually tallies your gross profit versus gross loss.
The Safety Bounds Check: If your strategy hasn't taken any losses yet (e.g., you are 5-0 to start), dividing average profit by average loss would trigger a Divide By Zero error. The script prevents this by defaulting dynRR to your bootstrap value until your first losing trade registers.
Dynamic Profit Targets: Note in the Execution section, your limit exit is now also scaling dynamically via limit=close + (stopDist * dynRR). If your historical R/R improves, your future limit orders will automatically stretch further.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
Adding a hard cap is the final failsafe of professional algorithmic trading. Even if your rolling 100-trade window gets extraordinarily "hot" (e.g., a 90% win rate) and the Kelly formula tells you it is mathematically optimal to risk 40% of your account, a hard cap prevents a single "black swan" event from destroying your portfolio on the 101st trade.
In Pine Script, you achieve this by adding a new user input for the maximum limit, and then wrapping your final risk calculation in a math.min() function. This forces the script to compare your calculated Kelly risk against your hard limit and always choose the smaller of the two numbers.
Here is the fully updated script with the Max Risk Cap integrated into the logic and the dashboard:
In Pine Script, you achieve this by adding a new user input for the maximum limit, and then wrapping your final risk calculation in a math.min() function. This forces the script to compare your calculated Kelly risk against your hard limit and always choose the smaller of the two numbers.
Here is the fully updated script with the Max Risk Cap integrated into the logic and the dashboard:
Code: Select all
//@version=5
strategy("Dynamic Kelly + Hard Cap", overlay=true, initial_capital=10000, default_qty_type=strategy.cash)
// =========================================================================
// 1. BOOTSTRAP INPUTS
// =========================================================================
i_initialWinRate = input.float(50.0, title="Bootstrap Win Rate (%)", minval=1.0, maxval=99.0, group="Kelly Parameters") / 100.0
i_initialRR = input.float(2.0, title="Bootstrap Reward/Risk", minval=0.1, group="Kelly Parameters")
i_fraction = input.float(0.5, title="Kelly Fraction (0.5 = Half Kelly)", minval=0.1, maxval=1.0, step=0.1, group="Kelly Parameters")
i_lookback = input.int(100, title="Rolling Trade Window", minval=10, maxval=500, group="Kelly Parameters")
// =========================================================================
// 2. RISK MANAGEMENT INPUTS (The Hard Cap)
// =========================================================================
i_atrLen = input.int(14, title="ATR Length for Stop", group="Risk Management")
i_atrMult = input.float(1.5, title="ATR Multiplier for Stop Distance", group="Risk Management")
i_maxRisk = input.float(5.0, title="Absolute Max Risk Cap (%)", minval=0.1, maxval=20.0, step=0.5, group="Risk Management") / 100.0
// =========================================================================
// 3. DYNAMIC EDGE CALCULATION
// =========================================================================
var float dynWinRate = i_initialWinRate
var float dynRR = i_initialRR
int totalTrades = strategy.closedtrades
if totalTrades > 0
int wins = 0
float grossProfit = 0.0
float grossLoss = 0.0
int winCount = 0
int lossCount = 0
int startIdx = math.max(0, totalTrades - i_lookback)
int tradesToAnalyze = totalTrades - startIdx
if tradesToAnalyze > 0
for i = startIdx to totalTrades - 1
float profit = strategy.closedtrades.profit(i)
if profit > 0
wins += 1
grossProfit += profit
winCount += 1
else if profit < 0
grossLoss += math.abs(profit)
lossCount += 1
dynWinRate := wins / tradesToAnalyze
float avgWin = winCount > 0 ? grossProfit / winCount : 0.0
float avgLoss = lossCount > 0 ? grossLoss / lossCount : 0.0
dynRR := avgLoss > 0 ? avgWin / avgLoss : i_initialRR
// =========================================================================
// 4. THE KELLY MATH + HARD CAP
// =========================================================================
fullKelly = dynWinRate - ((1.0 - dynWinRate) / dynRR)
// Step 1: Apply fractional safety brake (and bound to 0 if edge is negative)
fractionalKelly = math.max(0, fullKelly * i_fraction)
// Step 2: Apply the Hard Cap (picks the smaller of your Cap or the Kelly calculation)
appliedRisk = math.min(i_maxRisk, fractionalKelly)
riskAmount = strategy.equity * appliedRisk
atr = ta.atr(i_atrLen)
stopDist = atr * i_atrMult
positionSize = stopDist > 0 ? (riskAmount / stopDist) : 0
// =========================================================================
// 5. DUMMY ENTRY LOGIC
// =========================================================================
fastSma = ta.sma(close, 10)
slowSma = ta.sma(close, 20)
longTrigger = ta.crossover(fastSma, slowSma)
shortTrigger = ta.crossunder(fastSma, slowSma)
// =========================================================================
// 6. EXECUTION
// =========================================================================
if longTrigger and strategy.opentrades == 0 and appliedRisk > 0
strategy.entry("Long", strategy.long, qty=positionSize)
strategy.exit("Exit Long", "Long", stop=close - stopDist, limit=close + (stopDist * dynRR))
if shortTrigger and strategy.opentrades == 0 and appliedRisk > 0
strategy.entry("Short", strategy.short, qty=positionSize)
strategy.exit("Exit Short", "Short", stop=close + stopDist, limit=close - (stopDist * dynRR))
// =========================================================================
// 7. DASHBOARD UI
// =========================================================================
var table infoTable = table.new(position.top_right, 2, 5, border_width=1, border_color=color.gray, frame_color=color.black, frame_width=1)
if barstate.islast
table.cell(infoTable, 0, 0, "Rolling Win Rate", text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 1, 0, str.tostring(dynWinRate * 100, "#.##") + "%", text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 0, 1, "Rolling R/R", text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 1, 1, str.tostring(dynRR, "#.##"), text_color=color.white, bgcolor=color.new(color.purple, 20))
table.cell(infoTable, 0, 2, "Fractional Kelly %", text_color=color.white, bgcolor=color.new(color.blue, 20))
table.cell(infoTable, 1, 2, str.tostring(fractionalKelly * 100, "#.##") + "%", text_color=color.white, bgcolor=color.new(color.blue, 20))
// Highlights red if the cap is actively restricting the trade size
isCapped = fractionalKelly > i_maxRisk
capColor = isCapped ? color.new(color.red, 0) : color.new(color.teal, 20)
table.cell(infoTable, 0, 3, isCapped ? "RISK CAPPED AT MAX" : "Applied Risk", text_color=color.white, bgcolor=capColor)
table.cell(infoTable, 1, 3, str.tostring(appliedRisk * 100, "#.##") + "%", text_color=color.white, bgcolor=capColor)
table.cell(infoTable, 0, 4, "Current Risk ($)", text_color=color.white, bgcolor=color.new(color.gray, 20))
table.cell(infoTable, 1, 4, "$" + str.tostring(riskAmount, "#.##"), text_color=color.white, bgcolor=color.new(color.gray, 20))Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 1% Rule Isn't Optional
The Modification Breakdown
The Inputs: We added i_maxRisk = input.float(5.0...) / 100.0. This gives you a UI slider in the settings menu to adjust the ceiling without touching the code.
The Logic: appliedRisk = math.min(i_maxRisk, fractionalKelly). If your fractional Kelly dictates 8%, but your cap is 5%, math.min forces the script to select 0.05.
The Visual Warning: The UI dashboard code at the bottom now includes an isCapped boolean check. If your Kelly calculations exceed your hard limit, the dashboard row turns solid red and reads "RISK CAPPED AT MAX" so you know immediately when your algorithm's edge is outperforming your allowed risk parameters.
The Inputs: We added i_maxRisk = input.float(5.0...) / 100.0. This gives you a UI slider in the settings menu to adjust the ceiling without touching the code.
The Logic: appliedRisk = math.min(i_maxRisk, fractionalKelly). If your fractional Kelly dictates 8%, but your cap is 5%, math.min forces the script to select 0.05.
The Visual Warning: The UI dashboard code at the bottom now includes an isCapped boolean check. If your Kelly calculations exceed your hard limit, the dashboard row turns solid red and reads "RISK CAPPED AT MAX" so you know immediately when your algorithm's edge is outperforming your allowed risk parameters.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.