Hi All,
I am currently new to MT4 and I want to compute for the pips with minimal hard coding. When coding for currency AUDCHF, I get the following info from MarketInfo():
1. Lot Size = 100000
2. Tick Value = 1.089...
3. Tick Size = 1e-05
What I want to do is that I have an integer pip value that I want to add to the existing Bid/Ask. Say this value is 20. I have this formula:
From the tick size info, it computes for the pippette, and I have to multiply by 10 (hard-coded) in order to get it correct, which I want to avoid to have some flexibility for other currencies. Is there any method that I can use to calculate the pips instead of manually multiplying by 10?
Another questions that I have:
- what is tick value? Is this something that I can use for calculating risk management? It is advisable to do this or just stick with manual computation of standard lot then multiple by $10, mini lot then multiply by $1 and so on. Is there anything that I can use programatically to get the amount based on the lot size?
My questions would seem to be very mundane but bear with me since I am still starting. Thanks.
I know what you want. You know correctly what you want and what you are asking for.
This topic (with the answers we need) are extremely important and this is a VERY complex topic,. for the answer to be simple.. Lol..
My best answer, is to put here some other threads about this topic. Learning how this relations works are NOT EASY, because they are somehow confusing when learning.
But you must learn and know it 100%.
Take a read on the thread below
https://www.mql5.com/en/forum/365781
- 2021.03.26
- www.mql5.com
I know what you want. You know correctly what you want and what you are asking for.
This topic (with the answers we need) are extremely important and this is a VERY complex topic,. for the answer to be simple.. Lol..
My best answer, is to put here some other threads about this topic. Learning how this relations works are NOT EASY, because they are somehow confusing when learning.
But you must learn and know it 100%.
Take a read on the thread below
https://www.mql5.com/en/forum/365781
Looks like I might be jumping the gun here with regards to the tick values and all. So maybe I'll stick to the first part of the question first.
1. Lot Size = 100000
2. Tick Value = 1.089...
3. Tick Size = 1e-05
What I want to do is that I have an integer pip value that I want to add to the existing Bid/Ask. Say this value is 20. I have this formula:
double getPipsFromDistance(double distance) { double dblTickSize = MarketInfo(Symbol(), MODE_TICKSIZE); double pipValue = distance * dblTickSize; return pipValue; }
From the tick size info, it computes for the pippette, and I have to multiply by 10 (hard-coded) in order to get it correct, which I want to avoid to have some flexibility for other currencies. Is there any method that I can use to calculate the pips instead of manually multiplying by 10?
Are there any values that I can use to get the 10 multiplier? Or I really dont have a choice?
To further clarify, what I am trying to do is something like IntToPipsValue(), where say, 20 can be converted to 0.002
Forum on trading, automated trading systems and testing trading strategies
any suggestions for getting the required lot size for certain risk percentage ?
William Roeder, 2021.03.18 15:26
Risk depends on your initial stop loss, lot size, and the value of the symbol. It does not depend on margin and leverage. No SL means you have infinite risk. Never risk more than a small percentage of your trading funds, certainly less than 2% per trade, 6% total.
-
You place the stop where it needs to be — where the reason for the trade is no longer valid. E.g. trading a support bounce the stop goes below the support.
-
AccountBalance * percent/100 = RISK = OrderLots * (|OrderOpenPrice - OrderStopLoss| * DeltaPerLot + CommissionPerLot) (Note OOP-OSL includes the spread, and DeltaPerLot is usually around $10/pip but it takes account of the exchange rates of the pair vs. your account currency.)
-
Do NOT use TickValue by itself - DeltaPerLot and verify that MODE_TICKVALUE is returning a value in your deposit currency, as promised by the documentation, or whether it is returning a value in the instrument's base currency.
MODE_TICKVALUE is not reliable on non-fx instruments with many brokers - MQL4 programming forum 2017.10.10
Is there an universal solution for Tick value? - Currency Pairs - General - MQL5 programming forum 2018.02.11
Lot value calculation off by a factor of 100 - MQL5 programming forum 2019.07.19 -
You must normalize lots properly and check against min and max.
-
You must also check FreeMargin to avoid stop out
Most pairs are worth about $10 per PIP. A $5 risk with a (very small) 5 PIP SL is $5/$10/5 or 0.1 Lots maximum.
Forum on trading, automated trading systems and testing trading strategies
Formula to get the right lot size to recover my open losing trade
Fernando Carreiro, 2021.07.21 05:16
I know that! And I have already said that the calculation for Risk and S/L, is the same as for Reward and T/P. Just invert the direction. It is the same thing!
Volume in lots = ( [Reward] * [Tick Size] ) / ( [T/P Size] * [Tick Value] )
If the Symbol is EURUSD, then [Tick Value] = $1.00, [Tick Size] = 0.00001 and [T/P Size] = 80 pips = 0.00800, [Reward] = $500.00
Volume = ($500 * 0.00001) / (0.00800 * $1) = 0.005 / 0.008 = 0.625 Lots = 0.63 Lots
This code will calculate the proper tickvalue for Forex, Crypto, Gold, CFD and indices.
//+------------------------------------------------------------------+ //| TickValuePerLot in account currency. | //+------------------------------------------------------------------+ double mTickValue(string symbol = NULL) { if(symbol == NULL) symbol = _Symbol; //--- Some brokers return incorrect values for TICK_VALUE. long CalcMode = SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE); if((CalcMode == SYMBOL_CALC_MODE_CFD) || (CalcMode == SYMBOL_CALC_MODE_CFDINDEX) || (CalcMode == SYMBOL_CALC_MODE_CFDLEVERAGE)) { double TickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); double LotSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE); double TickValue = TickSize * LotSize; const string prof = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT); const string acc = AccountInfoString(ACCOUNT_CURRENCY); //--- converting into deposit currency. if(prof != acc) { TickValue *= GetCrossRate(prof, acc); } return TickValue; } return (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE)); } //+------------------------------------------------------------------+ //| PointValuePerLot in account currency. | //+------------------------------------------------------------------+ double mPointValue(string symbol = NULL) { if(symbol == NULL) symbol = _Symbol; double TickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); double PointSize = SymbolInfoDouble(symbol, SYMBOL_POINT); return mTickValue(symbol) / TickSize * PointSize; } //+------------------------------------------------------------------+ //| Get the cross-rate for the profit/account symbol | //+------------------------------------------------------------------+ double GetCrossRate(string curr_prof, string curr_acc) { //--- compare case-insensitive if(StringCompare(curr_prof, curr_acc, false) == 0) { return (1.0); } //--- string symbol = curr_prof + curr_acc; if(CheckMarketWatch(symbol)) { double bid = SymbolInfoDouble(symbol, SYMBOL_BID); if(bid != 0.0) return (bid); } //--- Try the inverse symbol symbol = curr_acc + curr_prof; if(CheckMarketWatch(symbol)) { double ask = SymbolInfoDouble(symbol, SYMBOL_ASK); if(ask != 0.0) return (1 / ask); } //--- Print(__FUNCTION__, ": Error, cannot get cross rate for ", curr_prof + curr_acc); return (0.0); } //+------------------------------------------------------------------+ //| Checks if symbol is selected in the MarketWatch | //| and adds symbol to the MarketWatch, if necessary | //+------------------------------------------------------------------+ bool CheckMarketWatch(string symbol) { ResetLastError(); //--- check if symbol is selected in the MarketWatch if(!SymbolInfoInteger(symbol,SYMBOL_SELECT)) { if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL) { //printf(__FUNCTION__+": Unknown symbol '%s'",symbol); return(false); } if(!SymbolSelect(symbol,true)) { printf(__FUNCTION__+": Error adding symbol %d",GetLastError()); return(false); } printf(__FUNCTION__+": Symbol '%s' is added in the MarketWatch.",symbol); } //--- succeed return(true); } //+------------------------------------------------------------------+
Here is another shorter code to calculate the tickvalue.
//+------------------------------------------------------------------+ //| TickValuePerLot in account currency. | //+------------------------------------------------------------------+ double mTickValue(string symbol = NULL) { if(symbol == NULL) symbol = _Symbol; //--- Some brokers return incorrect values for TICK_VALUE. long CalcMode = SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE); if((CalcMode == SYMBOL_CALC_MODE_CFD) || (CalcMode == SYMBOL_CALC_MODE_CFDINDEX) || (CalcMode == SYMBOL_CALC_MODE_CFDLEVERAGE)) { double MaxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); double Price = SymbolInfoDouble(symbol, SYMBOL_ASK); double TickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); double Profit = 0; if(OrderCalcProfit(ORDER_TYPE_BUY, symbol, 100 * MaxLot, Price, Price + TickSize, Profit) && Profit > 0) { return Profit / (100 * MaxLot); } } return (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE)); }
Edit: I'm sorry, I didn't notice the OP wants code for MT4
Here is another shorter code to calculate the tickvalue.
Edit: I'm sorry, I didn't notice the OP wants code for MT4
I do have a similar functionset in my library. SInce your code shows to be valid only for certain types of calculation modes, I was wondering if my code takes this into respect or if I need to adjust it maybe to have it generalized.
May I ask to take a look at this code and share improvements to it, please.
//+------------------------------------------------------------------+ //| AccountCurrencySymbolProfit() | //+------------------------------------------------------------------+ double AccountCurrencySymbolProfit(const string symbol, const double open_price, const double close_price, const double vol = 1.00) { // Local cache static double c_tick_value = NULL; static int c_digit_factor = NULL; static string c_symbol = NULL; // Init or update cache if(symbol != c_symbol) { c_symbol = symbol; c_tick_value = AccountCurrencySymbolTickValue(symbol, vol); c_digit_factor = MathPow(10, SymbolInfoInteger(symbol, SYMBOL_DIGITS)); } // Calculate profit return(fabs(open_price - close_price) * c_digit_factor * c_tick_value); } //+------------------------------------------------------------------+ //| AccountCurrencySymbolTickValue() | //+------------------------------------------------------------------+ double AccountCurrencySymbolTickValue(const string symbol, const double vol = 1.00) { // Const static const static bool _is_indicator = MQLInfoInteger(MQL_PROGRAM_TYPE) == PROGRAM_INDICATOR; // Local cache static double c_digit_factor = NULL; static double c_contract_size = NULL; static double c_tick_multiply = NULL; static double _vol_min = NULL; static double _vol_max = NULL; static bool m_hidden_currency = false; static bool m_hidden_rev_quote = false; static bool rev_quote = false; static string c_symbol = NULL; static string a_currency = NULL; static string m_currency = NULL; static string m_hidden_symbol = NULL; // Cache update function if(c_symbol != symbol) { // Temporals const double c_factor = MathPow(10, MathDigits(SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE))); double m_vol_min = NULL; double m_vol_max = DBL_MAX; // Globals c_symbol = symbol; c_tick_multiply = SymbolInfoDouble(c_symbol, SYMBOL_TRADE_TICK_SIZE) * c_factor; c_digit_factor = 1.0 / c_factor; c_contract_size = SymbolInfoDouble(c_symbol, SYMBOL_TRADE_CONTRACT_SIZE); m_currency = SymbolInfoString(c_symbol, SYMBOL_CURRENCY_MARGIN); rev_quote = (m_currency == SymbolInfoString(c_symbol, SYMBOL_CURRENCY_PROFIT)) ; a_currency = AccountInfoString(ACCOUNT_CURRENCY); // Margin currency is not account currency if(m_currency != a_currency) { m_hidden_symbol = SymbolFind(a_currency, m_currency, m_hidden_rev_quote); m_hidden_currency = true; m_vol_min = SymbolInfoDouble(m_hidden_symbol, SYMBOL_VOLUME_MIN); m_vol_max = SymbolInfoDouble(m_hidden_symbol, SYMBOL_VOLUME_MAX); // Preload hidden symbol if( (c_symbol != m_hidden_symbol) && (!SymbolInfoInteger(m_hidden_symbol, SYMBOL_SELECT)) && (SymbolSelect(m_hidden_symbol, true)) && (!_is_indicator) ) { Sleep(TerminalInfoInteger(TERMINAL_PING_LAST) / 500); if(!SymbolIsSynchronized(m_hidden_symbol)) { return(NULL); } } } // Globals _vol_min = MathMax(SymbolInfoDouble(c_symbol, SYMBOL_VOLUME_MIN), m_vol_min); _vol_max = MathMin(SymbolInfoDouble(c_symbol, SYMBOL_VOLUME_MAX), m_vol_max); } // Local init MqlTick _tick = {}; MqlTick m_tick = {}; double factor = NULL; double _vol = MathRange(vol, _vol_min, _vol_max); // Update tick data SymbolInfoTick(c_symbol, _tick); // Default to account currency is margin currency factor = (rev_quote) ? ((m_hidden_currency) ? _tick.bid : 1.0) : (1.0 / _tick.bid); // Currency factor if(m_hidden_currency) { SymbolInfoTick(m_hidden_symbol, m_tick); factor *= (m_tick.bid > NULL) ? ( ((1.0 / m_tick.bid) * ((m_hidden_rev_quote) && (!rev_quote)) ) + (m_tick.bid * ((!m_hidden_rev_quote) || (rev_quote))) ) : NULL; } // Return return(c_contract_size * c_digit_factor * factor * _vol * c_tick_multiply); } //+------------------------------------------------------------------+ //| SymbolFind() | //+------------------------------------------------------------------+ string SymbolFind(const string margin_currency, const string profit_currency, bool& rev_quote) { // Local init bool custom_symbol = false; string symbolname = NULL; string m_cur = NULL; string p_cur = NULL; string c_symbol = NULL; // Initially try guess a symbol if( (SymbolExist(margin_currency + profit_currency, custom_symbol)) && (!custom_symbol)) { c_symbol = margin_currency + profit_currency; rev_quote = true; return(c_symbol); } if( (SymbolExist(profit_currency + margin_currency, custom_symbol)) && (!custom_symbol)) { c_symbol = profit_currency + margin_currency; rev_quote = false; return(c_symbol); } // Search all available symbols for a match for(int cnt = 0; (cnt < SymbolsTotal(false)) && !IsStopped(); cnt++) { // Get symbol name symbolname = SymbolName(cnt, false); // Get margin currency m_cur = SymbolInfoString(symbolname, SYMBOL_CURRENCY_MARGIN); // Get profit currency (profit on price change) p_cur = SymbolInfoString(symbolname, SYMBOL_CURRENCY_PROFIT); // Check if found if( ( (m_cur == margin_currency) && (p_cur == profit_currency)) || ( (p_cur == margin_currency) && (m_cur == profit_currency)) ) { c_symbol = symbolname; if(SymbolExist(c_symbol, custom_symbol) && (!custom_symbol)) { rev_quote = (m_cur == margin_currency); return(c_symbol); } } } // Return failure return(NULL); } template <typename T, typename U, typename V> T MathRange(const T value, const U min, const V max) { return((value * (T)(((U)value >= min) && ((V)value <= max))) + (T)(min * (U)((U)value < min)) + (T)(max * (V)((V)value > max))); } template <typename T> int MathDigits(const T value) { return((int)MathRound(fabs(MathLog10((double)value)))); }
I do have a similar functionset in my library. SInce your code shows to be valid only for certain types of calculation modes, I was wondering if my code takes this into respect or if I need to adjust it maybe to have it generalized.
May I ask to take a look at this code and share improvements to it, please.
Your code calculates wrong tick_value for all symbols.
To calculate the proper tick_value:
tick_value (in profit currency) = volume in units * ticksize (price change) tick_value (converted to account currency) = tick_value (in profit currency) * profit currency/account currency exchange rate
The margin currency has no role in calculating the tick_value
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi All,
I am currently new to MT4 and I want to compute for the pips with minimal hard coding. When coding for currency AUDCHF, I get the following info from MarketInfo():
1. Lot Size = 100000
2. Tick Value = 1.089...
3. Tick Size = 1e-05
What I want to do is that I have an integer pip value that I want to add to the existing Bid/Ask. Say this value is 20. I have this formula:
From the tick size info, it computes for the pippette, and I have to multiply by 10 (hard-coded) in order to get it correct, which I want to avoid to have some flexibility for other currencies. Is there any method that I can use to calculate the pips instead of manually multiplying by 10?
Another questions that I have:
My questions would seem to be very mundane but bear with me since I am still starting. Thanks.