55//+------------------------------------------------------------------+
66#property copyright " Copyright © 2013-2022, EarnForex"
77#property link " https://www.earnforex.com/metatrader-expert-advisors/ChartPatternHelper/"
8- #property version " 1.10 "
8+ #property version " 1.11 "
99#property strict
1010
1111#include < stdlib.mqh>
@@ -71,8 +71,8 @@ bool HaveSell = false;
7171bool TCBusy = false ;
7272bool PostBuySLAdjustmentDone = false , PostSellSLAdjustmentDone = false ;
7373// For tick value adjustment:
74- string ProfitCurrency = " " , account_currency = " " , BaseCurrency = " " , ReferenceSymbol = NULL ;
75- bool ReferenceSymbolMode ;
74+ string ProfitCurrency = " " , account_currency = " " , BaseCurrency = " " , ReferenceSymbol = NULL , AdditionalReferenceSymbol = NULL ;
75+ bool ReferenceSymbolMode , AdditionalReferenceSymbolMode ;
7676int ProfitCalcMode ;
7777double TickSize ;
7878
@@ -1226,6 +1226,7 @@ void SetComment(string c)
12261226#define NONFOREX_SYMBOLS_ONLY 1
12271227double CalculateAdjustment ()
12281228{
1229+ double add_coefficient = 1 ; // Might be necessary for correction coefficient calculation if two pairs are used for profit currency to account currency conversion. This is handled differently in MT5 version.
12291230 if (ReferenceSymbol == NULL )
12301231 {
12311232 ReferenceSymbol = GetSymbolByCurrencies (ProfitCurrency , account_currency , FOREX_SYMBOLS_ONLY );
@@ -1241,13 +1242,34 @@ double CalculateAdjustment()
12411242 }
12421243 if (ReferenceSymbol == NULL )
12431244 {
1244- Print (" Error. Cannot detect proper currency pair for adjustment calculation. Profit currency: " , ProfitCurrency , " . Account currency: " , account_currency , " ." );
1245- return 1 ;
1245+ // The condition checks whether we are caclulating conversion coefficient for the chart's symbol or for some other.
1246+ // The error output is OK for the current symbol only because it won't be repeated ad infinitum.
1247+ // It should be avoided for non-chart symbols because it will just flood the log.
1248+ Print (" Couldn't detect proper currency pair for adjustment calculation. Profit currency: " , ProfitCurrency , " . Account currency: " , account_currency , " . Trying to find a possible two-symbol combination." );
1249+ if ((FindDoubleReferenceSymbol (" USD" )) // USD should work in 99.9% of cases.
1250+ || (FindDoubleReferenceSymbol (" EUR" )) // For very rare cases.
1251+ || (FindDoubleReferenceSymbol (" GBP" )) // For extremely rare cases.
1252+ || (FindDoubleReferenceSymbol (" JPY" ))) // For extremely rare cases.
1253+ {
1254+ Print (" Converting via " , ReferenceSymbol , " and " , AdditionalReferenceSymbol , " ." );
1255+ }
1256+ else
1257+ {
1258+ Print (" Adjustment calculation critical failure. Failed both simple and two-pair conversion methods." );
1259+ return 1 ;
1260+ }
12461261 }
12471262 }
1263+ if (AdditionalReferenceSymbol != NULL ) // If two reference pairs are used.
1264+ {
1265+ // Calculate just the additional symbol's coefficient and then use it in final return's multiplication.
1266+ MqlTick tick ;
1267+ SymbolInfoTick (AdditionalReferenceSymbol , tick );
1268+ add_coefficient = GetCurrencyCorrectionCoefficient (tick , AdditionalReferenceSymbolMode );
1269+ }
12481270 MqlTick tick ;
12491271 SymbolInfoTick (ReferenceSymbol , tick );
1250- return GetCurrencyCorrectionCoefficient (tick ) ;
1272+ return GetCurrencyCorrectionCoefficient (tick , ReferenceSymbolMode ) * add_coefficient ;
12511273}
12521274
12531275//+---------------------------------------------------------------------------+
@@ -1268,6 +1290,7 @@ string GetSymbolByCurrencies(const string base_currency, const string profit_cur
12681290 if (symbol_type == NONFOREX_SYMBOLS_ONLY ) continue ; // Avoid checking symbols of a wrong type.
12691291 // Get its base currency.
12701292 b_cur = SymbolInfoString (symbolname , SYMBOL_CURRENCY_BASE );
1293+ if (b_cur == " RUR" ) b_cur = " RUB" ;
12711294 }
12721295 else // Weird case for brokers that set conversion pairs as CFDs.
12731296 {
@@ -1278,6 +1301,7 @@ string GetSymbolByCurrencies(const string base_currency, const string profit_cur
12781301
12791302 // Get its profit currency.
12801303 string p_cur = SymbolInfoString (symbolname , SYMBOL_CURRENCY_PROFIT );
1304+ if (p_cur == " RUR" ) p_cur = " RUB" ;
12811305
12821306 // If the currency pair matches both currencies, select it in Market Watch and return its name.
12831307 if ((b_cur == base_currency ) && (p_cur == profit_currency ))
@@ -1291,15 +1315,68 @@ string GetSymbolByCurrencies(const string base_currency, const string profit_cur
12911315 return NULL ;
12921316}
12931317
1318+ //+----------------------------------------------------------------------------+
1319+ //| Finds reference symbols using 2-pair method. |
1320+ //| Results are returned via reference parameters. |
1321+ //| Returns true if found the pairs, false otherwise. |
1322+ //+----------------------------------------------------------------------------+
1323+ bool FindDoubleReferenceSymbol (const string cross_currency )
1324+ {
1325+ // A hypothetical example for better understanding:
1326+ // The trader buys CAD/CHF.
1327+ // account_currency is known = SEK.
1328+ // cross_currency = USD.
1329+ // profit_currency = CHF.
1330+ // I.e., we have to buy dollars with francs (using the Ask price) and then sell those for SEKs (using the Bid price).
1331+
1332+ ReferenceSymbol = GetSymbolByCurrencies (cross_currency , account_currency , FOREX_SYMBOLS_ONLY );
1333+ if (ReferenceSymbol == NULL ) ReferenceSymbol = GetSymbolByCurrencies (cross_currency , account_currency , NONFOREX_SYMBOLS_ONLY );
1334+ ReferenceSymbolMode = true ; // If found, we've got USD/SEK.
1335+
1336+ // Failed.
1337+ if (ReferenceSymbol == NULL )
1338+ {
1339+ // Reversing currencies.
1340+ ReferenceSymbol = GetSymbolByCurrencies (account_currency , cross_currency , FOREX_SYMBOLS_ONLY );
1341+ if (ReferenceSymbol == NULL ) ReferenceSymbol = GetSymbolByCurrencies (account_currency , cross_currency , NONFOREX_SYMBOLS_ONLY );
1342+ ReferenceSymbolMode = false ; // If found, we've got SEK/USD.
1343+ }
1344+ if (ReferenceSymbol == NULL )
1345+ {
1346+ Print (" Error. Couldn't detect proper currency pair for 2-pair adjustment calculation. Cross currency: " , cross_currency , " . Account currency: " , account_currency , " ." );
1347+ return false ;
1348+ }
1349+
1350+ AdditionalReferenceSymbol = GetSymbolByCurrencies (cross_currency , ProfitCurrency , FOREX_SYMBOLS_ONLY );
1351+ if (AdditionalReferenceSymbol == NULL ) AdditionalReferenceSymbol = GetSymbolByCurrencies (cross_currency , ProfitCurrency , NONFOREX_SYMBOLS_ONLY );
1352+ AdditionalReferenceSymbolMode = false ; // If found, we've got USD/CHF. Notice that mode is swapped for cross/profit compared to cross/acc, because it is used in the opposite way.
1353+
1354+ // Failed.
1355+ if (AdditionalReferenceSymbol == NULL )
1356+ {
1357+ // Reversing currencies.
1358+ AdditionalReferenceSymbol = GetSymbolByCurrencies (ProfitCurrency , cross_currency , FOREX_SYMBOLS_ONLY );
1359+ if (AdditionalReferenceSymbol == NULL ) AdditionalReferenceSymbol = GetSymbolByCurrencies (ProfitCurrency , cross_currency , NONFOREX_SYMBOLS_ONLY );
1360+ AdditionalReferenceSymbolMode = true ; // If found, we've got CHF/USD. Notice that mode is swapped for profit/cross compared to acc/cross, because it is used in the opposite way.
1361+ }
1362+ if (AdditionalReferenceSymbol == NULL )
1363+ {
1364+ Print (" Error. Couldn't detect proper currency pair for 2-pair adjustment calculation. Cross currency: " , cross_currency , " . Chart's pair currency: " , ProfitCurrency , " ." );
1365+ return false ;
1366+ }
1367+
1368+ return true ;
1369+ }
1370+
12941371//+------------------------------------------------------------------+
12951372//| Get profit correction coefficient based on current prices. |
12961373//| Valid for loss calculation only. |
12971374//+------------------------------------------------------------------+
1298- double GetCurrencyCorrectionCoefficient (MqlTick &tick )
1375+ double GetCurrencyCorrectionCoefficient (MqlTick &tick , const bool ref_symbol_mode )
12991376{
13001377 if ((tick .ask == 0 ) || (tick .bid == 0 )) return -1 ; // Data is not yet ready.
13011378 // Reverse quote.
1302- if (ReferenceSymbolMode )
1379+ if (ref_symbol_mode )
13031380 {
13041381 // Using Buy price for reverse quote.
13051382 return tick .ask ;
@@ -1320,6 +1397,12 @@ double GetPositionSize(double Entry, double StopLoss)
13201397 BaseCurrency = SymbolInfoString (Symbol (), SYMBOL_CURRENCY_BASE );
13211398 ProfitCalcMode = (int )MarketInfo (Symbol (), MODE_PROFITCALCMODE );
13221399 account_currency = AccountCurrency ();
1400+
1401+ // A rough patch for cases when account currency is set as RUR instead of RUB.
1402+ if (account_currency == " RUR" ) account_currency = " RUB" ;
1403+ if (ProfitCurrency == " RUR" ) ProfitCurrency = " RUB" ;
1404+ if (BaseCurrency == " RUR" ) BaseCurrency = " RUB" ;
1405+
13231406 double LotStep = MarketInfo (Symbol (), MODE_LOTSTEP );
13241407 int LotStep_digits = CountDecimalPlaces (LotStep );
13251408
0 commit comments