Warrior_EA/Money/MoneyIntelligent.mqh

72 lines
4.3 KiB
MQL5
Raw Permalink Normal View History

//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+