//+------------------------------------------------------------------+
//|                                          PositionSizerEA.mq5     |
//|                        Thin demo EA showing CPositionSizer with  |
//|                        all four risk models, selectable by input |
//+------------------------------------------------------------------+

#property strict

#include <PositionSizingEngine/PositionSizer.mqh>

//--- Input parameters
input ENUM_RISK_MODEL InpRiskModel             = RISK_MODEL_FIXED_FRACTIONAL; // active risk model
input double          InpFixedFractionalPct    = 1.0;                         // Model 1: risk % of balance per trade
input double          InpFixedMonetaryAmount   = 100.0;                       // Model 2: flat risk amount per trade
input ENUM_TIMEFRAMES InpAtrTimeframe          = PERIOD_H1;                   // Model 3: ATR timeframe
input int             InpAtrPeriod             = 14;                          // Model 3: ATR period
input double           InpAtrMultiplier        = 2.0;                         // Model 3: stop = ATR x this multiplier
input double           InpVolatilityRiskPct    = 1.0;                         // Model 3: risk % of balance per trade
input double           InpEquityCurveBasePct   = 1.0;                         // Model 4: base risk % with no drawdown
input double           InpDrawdownThresholdPct = 10.0;                        // Model 4: drawdown % at which scaling floors
input double           InpMinScalingFactor     = 0.25;                        // Model 4: floor on the scaling factor
input int              InpFixedStopPoints      = 300;                         // stop distance in points, used by Models 1, 2, and 4
input int              InpTakeProfitPoints     = 600;                         // take profit distance in points from entry
input ulong            InpMagicNumber          = 990022;                      // magic number stamped on every request

//--- Module-level state
CPositionSizer g_sizer;
datetime       g_last_open_day = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
   g_sizer.SetModel(InpRiskModel);
   g_sizer.ConfigureFixedFractional(InpFixedFractionalPct);
   g_sizer.ConfigureFixedMonetary(InpFixedMonetaryAmount);
   g_sizer.ConfigureVolatilityScaled(InpAtrTimeframe,InpAtrPeriod,InpAtrMultiplier,InpVolatilityRiskPct);
   g_sizer.ConfigureEquityCurve(InpEquityCurveBasePct,InpDrawdownThresholdPct,InpMinScalingFactor);

   ::PrintFormat("PositionSizerEA: initialized with risk model %s",::EnumToString(InpRiskModel));

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ::Print("PositionSizerEA: deinitialized, reason code " + (string)reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(void)
  {
   MqlDateTime now;
   ::TimeToStruct(::TimeCurrent(),now);

   datetime today_start = ::TimeCurrent() - (now.hour * 3600 + now.min * 60 + now.sec);

   if(g_last_open_day == today_start)
      return;

   g_last_open_day = today_start;

   DemonstrateSizing();
  }

//+------------------------------------------------------------------+
//| DemonstrateSizing                                                |
//+------------------------------------------------------------------+
void DemonstrateSizing(void)
  {
   string symbol = ::Symbol();

   CSizingResult result = g_sizer.CalculateLots(symbol,ORDER_TYPE_BUY,(double)InpFixedStopPoints);

   if(result.success)
     {
      ::PrintFormat("PositionSizerEA: model=%s lots=%.2f target_risk=%.2f actual_risk=%.2f stop_points=%.1f scaling=%.3f reason=%s",
                    ::EnumToString(result.model_used),result.lots,result.risk_amount,
                    result.actual_risk_amount,result.stop_points,result.scaling_factor,result.reason);
     }
   else
     {
      ::PrintFormat("PositionSizerEA: sizing failed for model=%s reason=%s",
                    ::EnumToString(result.model_used),result.reason);
     }
  }
//+------------------------------------------------------------------+