refactor:

This commit is contained in:
Toh4iem9
2025-09-26 11:42:22 +02:00
parent 5bb3930f04
commit d1620befca
+131 -41
View File
@@ -5,26 +5,39 @@
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, xxxxxxxx"
#property link ""
#property version "1.08" // Fixed case scope syntax error.
#property description "Calculates margin and shows swap cost with its calculation method."
#property version "6.02"
#property description "Calculates margin for a custom leverage using official MQL5 formulas."
//--- show the inputs window when the script is launched
#property script_show_inputs
//--- Input for the user to specify the position size
input double InpLotSize = 0.1;
//--- Enum for selectable leverage
enum ENUM_LEVERAGE
{
L_1_to_1 = 1,
L_1_to_2 = 2,
L_1_to_5 = 5,
L_1_to_10 = 10,
L_1_to_20 = 20,
L_1_to_30 = 30
};
//--- Input for the user to specify the position size and leverage
input double InpLotSize = 0.1;
input ENUM_LEVERAGE InpLeverage = L_1_to_1;
//--- Forward declarations
string DayOfWeekToString(ENUM_DAY_OF_WEEK day);
string SwapModeToString(ENUM_SYMBOL_SWAP_MODE mode, string base_curr, string profit_curr, string margin_curr);
double GetConversionRate(string from_currency, string to_currency);
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- Get the current symbol from the chart
string symbol = _Symbol;
string account_currency = AccountInfoString(ACCOUNT_CURRENCY);
if(!SymbolSelect(symbol, true))
{
@@ -34,69 +47,108 @@ void OnStart()
//--- 1. Gather Symbol Information ---
string description = SymbolInfoString(symbol, SYMBOL_DESCRIPTION);
string base_currency = SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE);
string profit_currency = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);
string account_currency = AccountInfoString(ACCOUNT_CURRENCY);
ENUM_DAY_OF_WEEK triple_swap_day = (ENUM_DAY_OF_WEEK)SymbolInfoInteger(symbol, SYMBOL_SWAP_ROLLOVER3DAYS);
ENUM_SYMBOL_SWAP_MODE swap_mode = (ENUM_SYMBOL_SWAP_MODE)SymbolInfoInteger(symbol, SYMBOL_SWAP_MODE);
string margin_currency = SymbolInfoString(symbol, SYMBOL_CURRENCY_MARGIN);
//--- 2. Calculate Required Margin (Always in Account Currency) ---
double margin_buy = 0, margin_sell = 0;
if(!OrderCalcMargin(ORDER_TYPE_BUY, symbol, InpLotSize, SymbolInfoDouble(symbol, SYMBOL_ASK), margin_buy) ||
!OrderCalcMargin(ORDER_TYPE_SELL, symbol, InpLotSize, SymbolInfoDouble(symbol, SYMBOL_BID), margin_sell))
//--- 2. Calculate Required Margin with CUSTOM LEVERAGE (Official Formulas) ---
double margin_1_to_1 = 0;
double contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
double current_price = SymbolInfoDouble(symbol, SYMBOL_ASK);
ENUM_SYMBOL_CALC_MODE calc_mode = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
switch(calc_mode)
{
Print("Error calculating margin. Error code: ", GetLastError());
return;
case SYMBOL_CALC_MODE_FOREX:
{
margin_1_to_1 = InpLotSize * contract_size;
break;
}
case SYMBOL_CALC_MODE_CFD:
case SYMBOL_CALC_MODE_CFDLEVERAGE:
case SYMBOL_CALC_MODE_EXCH_STOCKS:
case SYMBOL_CALC_MODE_SERV_COLLATERAL:
{
margin_1_to_1 = InpLotSize * contract_size * current_price;
break;
}
case SYMBOL_CALC_MODE_FUTURES:
case SYMBOL_CALC_MODE_EXCH_FUTURES:
case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
{
margin_1_to_1 = InpLotSize * SymbolInfoDouble(symbol, SYMBOL_MARGIN_INITIAL);
if(InpLeverage != L_1_to_1)
Print("Warning: Leverage simulation might be inaccurate for Futures as their margin is fixed.");
break;
}
case SYMBOL_CALC_MODE_CFDINDEX:
{
double tick_value = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
if(tick_size > 0)
margin_1_to_1 = InpLotSize * contract_size * tick_value / tick_size;
break;
}
default:
{
Print("Unsupported margin calculation mode for this symbol: ", EnumToString(calc_mode));
return;
}
}
//--- 3. Calculate Raw Swap Costs ---
double margin_required = margin_1_to_1 / (double)InpLeverage;
if(margin_currency != account_currency)
{
double conversion_rate = GetConversionRate(margin_currency, account_currency);
if(conversion_rate > 0)
margin_required *= conversion_rate;
else
Print("Warning: Could not find conversion rate from ", margin_currency, " to ", account_currency, ". Margin value is in ", margin_currency, ".");
}
//--- 3. Swap Calculation ---
ENUM_SYMBOL_SWAP_MODE swap_mode = (ENUM_SYMBOL_SWAP_MODE)SymbolInfoInteger(symbol, SYMBOL_SWAP_MODE);
double swap_long_cost = 0, swap_short_cost = 0;
double swap_long_raw = SymbolInfoDouble(symbol, SYMBOL_SWAP_LONG);
double swap_short_raw = SymbolInfoDouble(symbol, SYMBOL_SWAP_SHORT);
//--- The raw value is calculated without conversion
switch(swap_mode)
{
case SYMBOL_SWAP_MODE_POINTS:
{
swap_long_cost = swap_long_raw; // The value is in points
swap_short_cost = swap_short_raw;
break;
}
{ swap_long_cost = swap_long_raw; swap_short_cost = swap_short_raw; break; }
case SYMBOL_SWAP_MODE_CURRENCY_SYMBOL:
case SYMBOL_SWAP_MODE_CURRENCY_MARGIN:
case SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT:
{ swap_long_cost = InpLotSize * swap_long_raw; swap_short_cost = InpLotSize * swap_short_raw; break; }
case SYMBOL_SWAP_MODE_INTEREST_CURRENT: // Corrected from SYMBOL_CALC_MODE...
{
swap_long_cost = InpLotSize * swap_long_raw;
swap_short_cost = InpLotSize * swap_short_raw;
break;
}
case SYMBOL_SWAP_MODE_INTEREST_CURRENT:
{
double contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
double price = SymbolInfoDouble(symbol, SYMBOL_BID);
swap_long_cost = (InpLotSize * contract_size * price * (swap_long_raw / 100.0)) / 360.0;
swap_short_cost = (InpLotSize * contract_size * price * (swap_short_raw / 100.0)) / 360.0;
break;
}
default:
{
swap_long_cost = swap_long_raw;
swap_short_cost = swap_short_raw;
break;
}
{ swap_long_cost = swap_long_raw; swap_short_cost = swap_short_raw; break; }
}
//--- 4. Display the Results in the Experts Tab ---
string swap_unit = SwapModeToString(swap_mode, base_currency, profit_currency, account_currency);
string base_currency = SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE);
string profit_currency = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);
ENUM_DAY_OF_WEEK triple_swap_day = (ENUM_DAY_OF_WEEK)SymbolInfoInteger(symbol, SYMBOL_SWAP_ROLLOVER3DAYS);
string swap_unit = SwapModeToString(swap_mode, base_currency, profit_currency, margin_currency);
Print("--- Margin & Swap Calculation ---");
PrintFormat("Symbol: %s (%s)", symbol, description);
PrintFormat("Position Size: %.2f lots", InpLotSize);
PrintFormat("Simulated Leverage: 1:%d", (int)InpLeverage);
PrintFormat("Calculation Mode: %s", EnumToString(calc_mode));
Print("\n--- Required Margin ---");
PrintFormat("BUY Order: %.2f %s", margin_buy, account_currency);
PrintFormat("SELL Order: %.2f %s", margin_sell, account_currency);
PrintFormat("Margin for position: %.2f %s", margin_required, account_currency);
Print("\n--- Daily Swap Cost ---");
PrintFormat("Calculation Mode: %s", swap_unit);
@@ -120,11 +172,11 @@ string SwapModeToString(ENUM_SYMBOL_SWAP_MODE mode, string base_curr, string pro
case SYMBOL_SWAP_MODE_CURRENCY_SYMBOL:
return "In " + base_curr + " (Base Currency)";
case SYMBOL_SWAP_MODE_CURRENCY_MARGIN:
return "In " + margin_curr + " (Account Currency)";
return "In " + margin_curr + " (Margin Currency)";
case SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT:
return "In " + profit_curr + " (Quote/Profit Currency)"; // Based on terminal behavior
return "In " + AccountInfoString(ACCOUNT_CURRENCY) + " (Account Currency)";
case SYMBOL_SWAP_MODE_INTEREST_CURRENT:
return "Daily cost calculated from annual % in " + profit_curr;
return "Daily cost from annual % in " + profit_curr;
default:
return "Unknown Mode (" + (string)mode + ")";
}
@@ -155,5 +207,43 @@ string DayOfWeekToString(ENUM_DAY_OF_WEEK day)
return "Unknown";
}
}
//+------------------------------------------------------------------+
//| Gets the conversion rate between two currencies. |
//+------------------------------------------------------------------+
double GetConversionRate(string from_currency, string to_currency)
{
if(from_currency == to_currency)
return 1.0;
double rate = 0.0;
string pair_direct = from_currency + to_currency;
string pair_inverse = to_currency + from_currency;
SymbolSelect(pair_direct, true);
SymbolSelect(pair_inverse, true);
Sleep(50);
if(SymbolInfoDouble(pair_direct, SYMBOL_ASK, rate) && rate > 0)
return rate;
if(SymbolInfoDouble(pair_inverse, SYMBOL_BID, rate) && rate > 0)
return 1.0 / rate;
string majors[] = {"USD", "EUR", "GBP", "JPY"};
for(int i=0; i<ArraySize(majors); i++)
{
string major = majors[i];
if(from_currency != major && to_currency != major)
{
double rate1 = GetConversionRate(from_currency, major);
double rate2 = GetConversionRate(major, to_currency);
if(rate1 > 0 && rate2 > 0)
return rate1 * rate2;
}
}
return 0.0;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+