New EA and Indi
This commit is contained in:
444
Buffer EA/Include/MoneyManager.mqh
Normal file
444
Buffer EA/Include/MoneyManager.mqh
Normal file
@@ -0,0 +1,444 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MoneyManager.mqh |
|
||||
//| Universal Buffer Reader EA v2.0 |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025"
|
||||
#property link ""
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| CMoneyManager - Calculates lot sizes and manages daily profit |
|
||||
//+------------------------------------------------------------------+
|
||||
class CMoneyManager
|
||||
{
|
||||
private:
|
||||
double m_base_lot_size;
|
||||
bool m_use_percent_balance;
|
||||
double m_percent_of_balance_for_profit;
|
||||
double m_daily_profit_target_percent;
|
||||
|
||||
double m_min_lot;
|
||||
double m_max_lot;
|
||||
double m_lot_step;
|
||||
double m_point_value;
|
||||
double m_tick_value;
|
||||
|
||||
// State
|
||||
double m_daily_profit_accumulated;
|
||||
double m_daily_start_balance;
|
||||
|
||||
// Logging
|
||||
bool m_enable_debug;
|
||||
|
||||
public:
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CMoneyManager()
|
||||
{
|
||||
m_base_lot_size = 0.03;
|
||||
m_use_percent_balance = true;
|
||||
m_percent_of_balance_for_profit = 1.0;
|
||||
m_daily_profit_target_percent = 2.0;
|
||||
|
||||
m_min_lot = 0.01;
|
||||
m_max_lot = 100.0;
|
||||
m_lot_step = 0.01;
|
||||
m_point_value = 0;
|
||||
m_tick_value = 0;
|
||||
|
||||
m_daily_profit_accumulated = 0;
|
||||
m_daily_start_balance = 0;
|
||||
m_enable_debug = false;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
~CMoneyManager()
|
||||
{
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
void SetParameters(
|
||||
double base_lot_size,
|
||||
bool use_percent_balance, double percent_of_balance_for_profit,
|
||||
double daily_profit_target_percent,
|
||||
double min_lot, double max_lot, double lot_step,
|
||||
double point_value, double tick_value,
|
||||
bool enable_debug = false
|
||||
)
|
||||
{
|
||||
// Validate parameters
|
||||
if(base_lot_size <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid base lot size: ", base_lot_size, ". Using default 0.01");
|
||||
m_base_lot_size = 0.01;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_base_lot_size = base_lot_size;
|
||||
}
|
||||
|
||||
if(percent_of_balance_for_profit <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid percent of balance for profit: ", percent_of_balance_for_profit, ". Using default 1.0");
|
||||
m_percent_of_balance_for_profit = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_percent_of_balance_for_profit = percent_of_balance_for_profit;
|
||||
}
|
||||
|
||||
if(daily_profit_target_percent < 0)
|
||||
{
|
||||
Print("[ERROR] Invalid daily profit target percent: ", daily_profit_target_percent, ". Using default 2.0");
|
||||
m_daily_profit_target_percent = 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_daily_profit_target_percent = daily_profit_target_percent;
|
||||
}
|
||||
|
||||
if(min_lot <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid min lot: ", min_lot, ". Using default 0.01");
|
||||
m_min_lot = 0.01;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_min_lot = min_lot;
|
||||
}
|
||||
|
||||
if(max_lot <= 0 || max_lot < min_lot)
|
||||
{
|
||||
Print("[ERROR] Invalid max lot: ", max_lot, ". Using default 100.0");
|
||||
m_max_lot = 100.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_max_lot = max_lot;
|
||||
}
|
||||
|
||||
if(lot_step <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid lot step: ", lot_step, ". Using default 0.01");
|
||||
m_lot_step = 0.01;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lot_step = lot_step;
|
||||
}
|
||||
|
||||
if(point_value <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid point value: ", point_value);
|
||||
}
|
||||
m_point_value = point_value;
|
||||
|
||||
if(tick_value <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid tick value: ", tick_value);
|
||||
}
|
||||
m_tick_value = tick_value;
|
||||
|
||||
m_use_percent_balance = use_percent_balance;
|
||||
m_enable_debug = enable_debug;
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Parameters set:");
|
||||
Print(" Base lot size: ", m_base_lot_size);
|
||||
Print(" Use % balance: ", m_use_percent_balance);
|
||||
Print(" % of balance for profit: ", m_percent_of_balance_for_profit);
|
||||
Print(" Daily profit target %: ", m_daily_profit_target_percent);
|
||||
Print(" Min lot: ", m_min_lot, ", Max lot: ", m_max_lot, ", Lot step: ", m_lot_step);
|
||||
Print(" Point value: ", m_point_value, ", Tick value: ", m_tick_value);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set debug mode |
|
||||
//+------------------------------------------------------------------+
|
||||
void SetDebugMode(bool enable_debug)
|
||||
{
|
||||
m_enable_debug = enable_debug;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate lot size (pure function) |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateLotSize(
|
||||
bool is_buy,
|
||||
double open_price,
|
||||
double tp_price,
|
||||
double account_balance
|
||||
)
|
||||
{
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Calculating lot size...");
|
||||
Print(" Direction: ", (is_buy ? "BUY" : "SELL"));
|
||||
Print(" Open price: ", open_price);
|
||||
Print(" TP price: ", tp_price);
|
||||
Print(" Account balance: ", account_balance);
|
||||
}
|
||||
|
||||
// Validate inputs
|
||||
if(open_price <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid open price: ", open_price);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
if(tp_price <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid TP price: ", tp_price);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
if(account_balance <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid account balance: ", account_balance);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
// Calculate TP points
|
||||
double tp_points = 0;
|
||||
if(is_buy)
|
||||
{
|
||||
tp_points = (tp_price - open_price) / m_point_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
tp_points = (open_price - tp_price) / m_point_value;
|
||||
}
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print(" TP points: ", tp_points);
|
||||
}
|
||||
|
||||
if(tp_points <= 0)
|
||||
{
|
||||
Print("[WARNING] TP points <= 0. Using base lot size: ", m_base_lot_size);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
// Calculate base lot
|
||||
double base_lot = m_base_lot_size;
|
||||
if(m_use_percent_balance)
|
||||
{
|
||||
base_lot = CalculateBaseLot(tp_points, account_balance);
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print(" Base lot from % balance: ", base_lot);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print(" Using fixed base lot: ", base_lot);
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize and return
|
||||
double normalized_lot = NormalizeLotSize(base_lot);
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print(" Normalized lot: ", normalized_lot);
|
||||
Print("[MoneyManager] Lot size calculation complete: ", normalized_lot);
|
||||
}
|
||||
|
||||
return normalized_lot;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reset daily profit tracking |
|
||||
//+------------------------------------------------------------------+
|
||||
void ResetDailyProfit(double current_balance)
|
||||
{
|
||||
if(current_balance <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid current balance for daily profit reset: ", current_balance);
|
||||
return;
|
||||
}
|
||||
|
||||
m_daily_start_balance = current_balance;
|
||||
m_daily_profit_accumulated = 0;
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Daily profit tracking reset");
|
||||
Print(" Start balance: ", m_daily_start_balance);
|
||||
Print(" Target profit: ", GetDailyProfitTarget());
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if daily profit target reached |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsDailyProfitTargetReached()
|
||||
{
|
||||
if(m_daily_profit_target_percent <= 0)
|
||||
{
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Daily profit target disabled (0%)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
double target_profit = GetDailyProfitTarget();
|
||||
bool reached = (m_daily_profit_accumulated >= target_profit);
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Daily profit check:");
|
||||
Print(" Accumulated: ", m_daily_profit_accumulated);
|
||||
Print(" Target: ", target_profit);
|
||||
Print(" Reached: ", (reached ? "YES" : "NO"));
|
||||
}
|
||||
|
||||
return reached;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get daily profit target |
|
||||
//+------------------------------------------------------------------+
|
||||
double GetDailyProfitTarget()
|
||||
{
|
||||
if(m_daily_start_balance <= 0) return 0;
|
||||
return m_daily_start_balance * m_daily_profit_target_percent / 100.0;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get daily profit accumulated |
|
||||
//+------------------------------------------------------------------+
|
||||
double GetDailyProfitAccumulated()
|
||||
{
|
||||
return m_daily_profit_accumulated;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get daily profit percentage |
|
||||
//+------------------------------------------------------------------+
|
||||
double GetDailyProfitPercent()
|
||||
{
|
||||
if(m_daily_start_balance <= 0) return 0;
|
||||
return (m_daily_profit_accumulated / m_daily_start_balance) * 100.0;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set daily profit accumulated (for tracking) |
|
||||
//+------------------------------------------------------------------+
|
||||
void SetDailyProfitAccumulated(double value)
|
||||
{
|
||||
m_daily_profit_accumulated = value;
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Daily profit accumulated set to: ", value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate base lot based on % balance |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateBaseLot(double tp_points, double account_balance)
|
||||
{
|
||||
if(tp_points <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid TP points for base lot calculation: ", tp_points);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
if(m_tick_value <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid tick value for base lot calculation: ", m_tick_value);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
if(account_balance <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid account balance for base lot calculation: ", account_balance);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
double target_profit = account_balance * (m_percent_of_balance_for_profit / 100.0);
|
||||
double profit_per_lot = tp_points * m_tick_value;
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Base lot calculation:");
|
||||
Print(" Target profit: ", target_profit, " (", m_percent_of_balance_for_profit, "% of balance)");
|
||||
Print(" Profit per lot: ", profit_per_lot);
|
||||
}
|
||||
|
||||
if(profit_per_lot <= 0)
|
||||
{
|
||||
Print("[ERROR] Invalid profit per lot: ", profit_per_lot);
|
||||
return m_base_lot_size;
|
||||
}
|
||||
|
||||
double lot = target_profit / profit_per_lot;
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print(" Calculated lot: ", lot);
|
||||
}
|
||||
|
||||
return lot;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normalize lot size to broker requirements |
|
||||
//+------------------------------------------------------------------+
|
||||
double NormalizeLotSize(double lot)
|
||||
{
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print("[MoneyManager] Normalizing lot size: ", lot);
|
||||
}
|
||||
|
||||
// Round to lot step
|
||||
double rounded_lot = MathFloor(lot / m_lot_step) * m_lot_step;
|
||||
|
||||
if(m_enable_debug && rounded_lot != lot)
|
||||
{
|
||||
Print(" Rounded to lot step: ", rounded_lot, " (step: ", m_lot_step, ")");
|
||||
}
|
||||
|
||||
// Ensure within min/max
|
||||
double min_adjusted = MathMax(rounded_lot, m_min_lot);
|
||||
double max_adjusted = MathMin(min_adjusted, m_max_lot);
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
if(min_adjusted != rounded_lot)
|
||||
{
|
||||
Print(" Adjusted to min lot: ", min_adjusted, " (min: ", m_min_lot, ")");
|
||||
}
|
||||
if(max_adjusted != min_adjusted)
|
||||
{
|
||||
Print(" Adjusted to max lot: ", max_adjusted, " (max: ", m_max_lot, ")");
|
||||
}
|
||||
}
|
||||
|
||||
double normalized = NormalizeDouble(max_adjusted, 2);
|
||||
|
||||
if(m_enable_debug)
|
||||
{
|
||||
Print(" Final normalized lot: ", normalized);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
Reference in New Issue
Block a user