//+------------------------------------------------------------------+
//|                                     FixedFractionalModel.mqh     |
//+------------------------------------------------------------------+

#ifndef FIXED_FRACTIONAL_MODEL_MQH
#define FIXED_FRACTIONAL_MODEL_MQH

#include "RiskTypes.mqh"
#include "LotConverter.mqh"

//+------------------------------------------------------------------+
//| CFixedFractionalModel                                            |
//+------------------------------------------------------------------+
class CFixedFractionalModel
  {
private:
   CLotConverter     m_converter;   // shared money-per-point and normalization helper

public:
                     CFixedFractionalModel(void);
                    ~CFixedFractionalModel(void);

   CSizingResult     Calculate(const string symbol,const ENUM_ORDER_TYPE order_type,const double risk_pct,const double stop_points);
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CFixedFractionalModel::CFixedFractionalModel(void)
  {
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CFixedFractionalModel::~CFixedFractionalModel(void)
  {
  }

//+------------------------------------------------------------------+
//| Calculate                                                        |
//+------------------------------------------------------------------+
CSizingResult CFixedFractionalModel::Calculate(const string symbol,const ENUM_ORDER_TYPE order_type,const double risk_pct,const double stop_points)
  {
   CSizingResult result;
   result.model_used  = RISK_MODEL_FIXED_FRACTIONAL;
   result.stop_points = stop_points;

   if(risk_pct <= 0.0)
     {
      result.success = false;
      result.reason  = "risk_pct must be positive";
      return(result);
     }

   if(stop_points <= 0.0)
     {
      result.success = false;
      result.reason  = "stop_points must be positive";
      return(result);
     }

   double balance     = ::AccountInfoDouble(ACCOUNT_BALANCE);
   double risk_amount = balance * (risk_pct / 100.0);

   double actual_risk_amount = 0.0;
   double lots               = m_converter.LotsForRisk(symbol,order_type,risk_amount,stop_points,actual_risk_amount);

   if(lots <= 0.0)
     {
      result.success = false;
      result.reason  = "unable to compute a valid lot size for the requested risk";
      return(result);
     }

   result.success             = true;
   result.lots                = lots;
   result.risk_amount         = risk_amount;
   result.actual_risk_amount  = actual_risk_amount;
   result.scaling_factor      = 1.0;
   result.reason              = "fixed fractional sizing at " + DoubleToString(risk_pct,2) + "% of balance";

   return(result);
  }

#endif // FIXED_FRACTIONAL_MODEL_MQH
//+------------------------------------------------------------------+