1
0
포크 0
원본 프로젝트 animatedread/Warrior_EA
Warrior_EA/Money/MoneyIntelligent.mqh
AnimateDread d91cabc114 refactor(MoneyIntelligent): replace streak-chasing lot sizing with fractional-Kelly criterion
Optimize() scaled lot size off account trade-history streaks with no Magic-number
filter (picked up other EAs'/manual trades) and an unconfigurable m_factor stuck at
1.0 (Factor() was never wired from an input), so a 3-trade streak could triple lot
size or send it negative. It was also entirely disconnected from what the AI model
actually knows about the current setup.

Replaced both AdjustRiskAmount()'s linear confidence-only scale and Optimize()'s
streak multiplier with one edge-based model: p from the empirically calibrated
AI/DB confidence magnitude, b from the trade's real reward:risk ratio (newly
bridged from OpenParams() via g_TradeRewardRiskRatio), quarter-Kelly applied and
clamped so risk% can only ever scale down from its configured ceiling, never above it.
2026-07-18 17:39:58 -04:00

72 lines
4.3 KiB
MQL5

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//+------------------------------------------------------------------+
#include "MoneyRiskBase.mqh"
#include "..\Variables\ConfidenceBridge.mqh"
// Quarter-Kelly: only a quarter of the theoretical edge-optimal fraction is ever applied.
// Full Kelly is well documented as too volatile for live capital; quarter-Kelly is a
// conservative institutional default, deliberately chosen here for prop-firm-evaluation-style
// accounts that also carry hard daily-loss/drawdown limits (Signals\SignalRiskGuard.mqh).
#define KELLY_FRACTION_MULTIPLIER 0.25
// Floor so a thin/negative-edge estimate never scales risk% all the way to zero on a trade
// that already passed the signal's own entry threshold and Min_Risk_Reward_Ratio filter -
// it only ever gets sized down to a minimum, never fully skipped by Money.
#define KELLY_MIN_RISK_FRACTION 0.1
class CMoneyIntelligent : public CMoneyRiskBase
{
protected:
bool m_use_ai_lot; // true: scale risk % via the Kelly criterion below
int m_confidence_source; // CONFIDENCE_SOURCE underlying int (0=AI, 1=DB, 2=Blended)
public:
// Constructor
CMoneyIntelligent() : m_use_ai_lot(false), m_confidence_source(0) {}
void UseAIConfidenceLotSizing(bool value) { m_use_ai_lot = value; }
void ConfidenceSource(int value) { m_confidence_source = value; }
protected:
//--- CMoneyRiskBase::CalculateLotSize() hook - see CMoneyRiskBase's declaration comment.
virtual double AdjustRiskAmount(double riskAmount) override;
};
//+------------------------------------------------------------------+
//| Kelly-criterion risk% scaling - only active when Use_AI_Lot_Sizing|
//| is on. Unifies what used to be two disconnected mechanisms (a |
//| linear confidence-only scale here, plus an unrelated trade- |
//| history streak multiplier in a since-removed AdjustLotSize() |
//| override) into a single edge-based model that uses everything |
//| the NN and the trade's own risk math already know: |
//| p = estimated win probability, derived from the empirically |
//| calibrated AI/DB confidence magnitude (see |
//| ExpertSignalAIBase::CalibratedConfidenceMagnitude()'s |
//| m_confidenceCalScale - it's scaled against real OOS accuracy,|
//| not a raw uncalibrated softmax value) mapped from [0,1] onto |
//| [0.5,1.0] - zero confidence is a coin flip, full confidence |
//| is treated as near-certain. |
//| b = this specific trade's real reward:risk ratio, bridged from |
//| CExpertSignalCustom::OpenParams() via g_TradeRewardRiskRatio |
//| (Variables\ConfidenceBridge.mqh) - always >= Min_Risk_Reward |
//| _Ratio, since OpenParams() rejects thinner setups before |
//| Money is ever consulted. |
//| f* = p - (1-p)/b is the Kelly-optimal fraction; only |
//| KELLY_FRACTION_MULTIPLIER of it is used (see its own comment), |
//| then clamped to [KELLY_MIN_RISK_FRACTION, 1.0] so this can only |
//| ever scale the configured Money_Risk_Percent DOWN from its input |
//| ceiling, never above it - the same invariant this method has |
//| always guaranteed. |
//+------------------------------------------------------------------+
double CMoneyIntelligent::AdjustRiskAmount(double riskAmount)
{
if(!m_use_ai_lot)
return riskAmount;
if(g_TradeRewardRiskRatio <= 0.0)
return riskAmount * KELLY_MIN_RISK_FRACTION; // bridge not populated yet - defensive floor
double confidence = CombinedConfidence(m_confidence_source);
double p = 0.5 + 0.5 * confidence;
double b = g_TradeRewardRiskRatio;
double fKelly = MathMax(0.0, MathMin(1.0, p - (1.0 - p) / b));
double fraction = MathMax(KELLY_MIN_RISK_FRACTION, MathMin(1.0, fKelly * KELLY_FRACTION_MULTIPLIER));
return riskAmount * fraction;
}
//+------------------------------------------------------------------+