Today on SHOP.nyse I lost about $1k on a position that my EA is supposed to allocate 2% of my account equity (started with $15k) on. It's the same problem as described above i.e. the incorrect lot size being allocated but it is not just when trading AUS cfds. But in all these cases the lot size has been 10 contracts. For some stock cfd's that seems to mean different things or otherwise what am I missing. Please help.
Time | Position | Symbol | Type | Volume | Price | S / L | T / P | Time | Price | Commission | Swap | Profit |
2022.01.27 22:21:27 | 190685913 | SHOP.NYSE.a | sell | 10 | 817.281 | 919.535 | 635.078 | 2022.01.31 16:45:27 | 920.405 | 0.00 | -1.13 | -1 031.24 |
You have described your problem in detail, but what you have not done is provide real code that can be studied in order to help you. The little bit of code you provided is of no use. We cannot "guess" what is in the rest of code and we are just left with even more questions.
For example what is "m_money"? We have no idea what class it is or what its methods do. If you want us to properly look at your code for errors or problems, then you would have to supply either full source code, or in the least a working skeleton example that can illustrate the problem.
Short of this, there is not much we can do to help.
How's this?
#include <Trade\Trade.mqh> #include <Expert\Expert.mqh> #include <Trade\SymbolInfo.mqh> #include <Expert\Money\MoneyFixedRisk.mqh> #include <Tools\DateTime.mqh> //CTrade trade; CSymbolInfo m_symbol; CMoneyFixedRisk m_money; CTrade my_trade; // Trade direction input bool isLong; // Long input bool isShort; // Short // Position sizing double risk_percent = 2; void OnInit() { // Set details for new orders if(!CheckPositionOpen(_Symbol) && !CheckPendingOrderPlaced(_Symbol) && CheckHLINESPlacedOnChart()) { GlobalVariableSet("g" + _Symbol + "_position_opened", false); GlobalVariableSet("g" + _Symbol + "_timeframe", (ENUM_TIMEFRAMES)GetTradeTimeFrame(_Period)); GlobalVariableSet("g" + _Symbol + "_entry_level", NormalizeDouble(GetEntryLevel(_Symbol), (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS))); GlobalVariableSet("g" + _Symbol + "_sl", NormalizeDouble(GetInitialStopLossLevel(), (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS))); GlobalVariableSet("g" + _Symbol + "_tp", NormalizeDouble(GetProfitTarget(), (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS))); GlobalVariableSet("g" + _Symbol + "_vol", NormalizeDouble(GetTradeVolume(_Symbol), 2)); GlobalVariableSet("g" + _Symbol + "_deviation", GetMaxDeviationPointsAllowed(_Symbol, max_gap_r, GetEntryLevel(_Symbol), GetInitialStopLossLevel())); GlobalVariablesFlush(); } // Get open position details if(PositionSelect(_Symbol)) { GlobalVariableSet("g" + _Symbol + "_position_opened", true); GlobalVariableSet("g" + _Symbol + "_timeframe", (ENUM_TIMEFRAMES)GetTradeTimeFrame(_Period)); GlobalVariableSet("g" + _Symbol + "_entry_level", PositionGetDouble(POSITION_PRICE_OPEN)); GlobalVariableSet("g" + _Symbol + "_sl", PositionGetDouble(POSITION_SL)); GlobalVariableSet("g" + _Symbol + "_tp", PositionGetDouble(POSITION_TP)); GlobalVariableSet("g" + _Symbol + "_vol", PositionGetDouble(POSITION_VOLUME)); GlobalVariablesFlush(); } } double GetTradeVolume(string symbol) { double return_value = 0; ENUM_TIMEFRAMES timeframe = (ENUM_TIMEFRAMES)GlobalVariableGet("g" + symbol + "_timeframe"); double entry = GlobalVariableGet("g" + symbol + "_entry_level"); double sl = GlobalVariableGet("g" + symbol + "_sl"); m_symbol.Name(symbol); m_money.Init(GetPointer(m_symbol), timeframe, (double)SymbolInfoDouble(symbol, SYMBOL_POINT)); m_money.Percent(risk_percent); if(isLong) return_value = m_money.CheckOpenLong(entry, sl); if(isShort) return_value = m_money.CheckOpenShort(entry, sl); return_value = NormalizeDouble(return_value, 2); return return_value; }
The entry level and initial sl are derived from HLINES I drop on the chart around pivot levels and the TP is the same distance from the entry as the sl.
Thanks for your help I didn't think anyone would get back to me.
Thanks for your help I didn't think anyone would get back to me.
I’m going to help by making you test and debug your own code. It may not seem so “nice”, but it will help you learn and understand it better in the long run.
- Take your example code, put it into a “script” (not an EA) so it can be tested more easily.
- Simplify it as much as possible and remove all references to Terminal Global Variables. Just make it calculate the trade volume based on user supplied inputs for the variables you need, like stop-loss, etc.
- Add some code for it to “Print” the results of the "GetTradeVolume", as well as the inputs and symbol info, to the Experts tab log.
- Attach it to different charts of the various symbols you wish to test and look at the results.
- Compile a table of those "prints" for each symbol and post them here with your test code.
Why am I suggesting this? Well, we do not work with your broker, and we do not know if the “contract” details supplied by the broker are flawed or not, or if the values in the "Global variables" are correct or not. So by having your results to compare with tests we can run on our own setups, we should be able to find the cause or in the very least offer further guidance into further testing until a cause can be found.
As it stands now, we cannot possibly test your code on our end, nor do we have the foggiest idea about your setup and the symbols you are testing.
In summary, help us help you!
Also, as a matter of code consistency, your "init" line would be better like this:
m_money.Init( GetPointer( m_symbol ), timeframe, m_symbol.Point() );
It may not be that important in your example, but it helps for portability and future proofing.
I’m going to help by making you test and debug your own code. It may not seem so “nice”, but it will help you learn and understand it better in the long run.
- Take your example code, put it into a “script” (not an EA) so it can be tested more easily.
- Simplify it as much as possible and remove all references to Terminal Global Variables. Just make it calculate the trade volume based on user supplied inputs for the variables you need, like stop-loss, etc.
- Add some code for it to “Print” the results of the "GetTradeVolume", as well as the inputs and symbol info, to the Experts tab log.
- Attach it to different charts of the various symbols you wish to test and look at the results.
- Compile a table of those "prints" for each symbol and post them here with your test code.
Why am I suggesting this? Well, we do not work with your broker, and we do not know if the “contract” details supplied by the broker are flawed or not, or if the values in the "Global variables" are correct or not. So by having your results to compare with tests we can run on our own setups, we should be able to find the cause or in the very least offer further guidance into further testing until a cause can be found.
As it stands now, we cannot possibly test your code on our end, nor do we have the foggiest idea about your setup and the symbols you are testing.
In summary, help us help you!
Thanks very much for this.
Ok, here is the script..
#include <Trade\Trade.mqh> #include <Expert\Money\MoneyFixedRisk.mqh> CSymbolInfo m_symbol; CMoneyFixedRisk m_money; CTrade my_trade; bool isLong; bool isShort = true; double entry = 16.471; double sl = 19.000; int risk_percent = 2; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- double vol = GetTradeVolume(_Symbol); Print("entry: ", entry); Print("sl: ", sl); Print("lots: ", vol); Print("point: ", SymbolInfoDouble(_Symbol, SYMBOL_POINT)); Print("tick_size: ", SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE)); Print("tick_value: ", SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE)); Print("contract_size: ", SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE)); Print("vol_min: ", SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double GetTradeVolume(string symbol) { double return_value = 0; ENUM_TIMEFRAMES timeframe = _Period; m_symbol.Name(symbol); m_money.Init(GetPointer(m_symbol), timeframe, m_symbol.Point()); m_money.Percent(risk_percent); if(isLong) return_value = m_money.CheckOpenLong(entry, sl); if(isShort) return_value = m_money.CheckOpenShort(entry, sl); return_value = NormalizeDouble(return_value, 2); return return_value; }
And here is the output. I've added a couple rows from data taken from the transaction statment marked with an "*". The calculated lot size will differ because of a different account balance now than before.
SHOP.nyse | GPS.nyse | WES.asx | |
stop entry | 817.539 | 16.471 | 53.738 |
initial sl | 1000.000 | 19.000 | 56.000 |
lots calc | 10.0 | 99.0 | 10.0 |
lots used* | 10 | 114 | 10 |
point | 0.001 | 0.001 | 0.001 |
tick_size | 0.001 | 0.001 | 0.001 |
tick_value | 0.001 | 0.001 | 0.0 |
contract_size | 1.0 | 1.0 | 1.0 |
vol_min | 10.0 | 10.0 | 10.0 |
exit* | 920.405 | 17.022 | 51.48 |
points to exit | -102.87 | -0.55 | 2.26 |
actual profit* | -1 031.24 | -63.04 | 16.02 |
The starting account balance was $15k so for risking 2%/trade it doesn't make sense that SHOP would have a -$1k loss when there wasn't a gap or significant slippage and that GPS would represent a bigger loss than WES's profit margin.
Please note that according to your table, WES.asx is reporting a Tick Value of 0.0, which is invalid and will mess with your calculation. Your broker is not reporting it correctly.
Here is my take on the script:
#include <Trade\AccountInfo.mqh> #include <Trade\SymbolInfo.mqh> #include <Expert\Money\MoneyFixedRisk.mqh> input double i_dbEntryPrice = 16.471, i_dbStopLossPrice = 19.000, i_dbRiskPercentage = 2.0; void OnStart() { bool bIsLong = i_dbEntryPrice > i_dbStopLossPrice, bIsShort = i_dbEntryPrice < i_dbStopLossPrice; if( bIsLong || bIsShort ) { CSymbolInfo oSymbol; if( oSymbol.Name( _Symbol ) ) { CMoneyFixedRisk oMoney; if( oMoney.Init( GetPointer( oSymbol ), _Period, oSymbol.Point() ) ) { oMoney.Percent( i_dbRiskPercentage ); CAccountInfo oAccountInfo; double dbVolume = bIsLong ? oMoney.CheckOpenLong( i_dbEntryPrice, i_dbStopLossPrice ) : oMoney.CheckOpenShort( i_dbEntryPrice, i_dbStopLossPrice ); Print( "Inputs:" ); Print( " Entry: ", DoubleToString( i_dbEntryPrice, oSymbol.Digits() ) ); Print( " S/L: ", DoubleToString( i_dbStopLossPrice, oSymbol.Digits() ) ); Print( " Risk %: ", DoubleToString( i_dbRiskPercentage, 3 ) ); Print( "Output:" ); Print( " Volume: ", dbVolume ); Print( "Account:" ); Print( " Balance: ", DoubleToString( oAccountInfo.Balance(), 2 ), " (", oAccountInfo.Currency(), ")" ); Print( "Symbol:" ); Print( " Point size: ", DoubleToString( oSymbol.Point(), oSymbol.Digits() ) ); Print( " Tick size: ", DoubleToString( oSymbol.TickSize(), oSymbol.Digits() ) ); Print( " Tick value: ", oSymbol.TickValue() ); Print( " Tick value (profit): ", oSymbol.TickValueProfit() ); Print( " Tick value (loss): ", oSymbol.TickValueLoss() ); Print( " Lots (minimum): ", oSymbol.LotsMin() ); Print( " Lots (maximum): ", oSymbol.LotsMax() ); Print( " Lots (step): ", oSymbol.LotsStep() ); } else Print( "Error: Unable to initialise fixed risk money management!" ); } else Print( "Error: Unable to assign symbol name!" ); } else Print( "Error: Invalid entry and/or stop-loss price!" ); };

- 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 there,
Thanks for checking this out and offering your advice.
My EA places orders according to levels I manually specify. I've only been using it on US share CFDs until yesterday when I used it on a AUS share CFD. It looks like the function that calculates lot size doesn't work on AUS orders as it does on US orders.
To demonstrate this error in action, the below screen shot shows wes.asx has a profit of $4.24 while gps.nyse has a profit of $49.13.
The below screenshot shows that wes is about 25% of the way to the TP while gps is less than that, however wes shows a tenth of the profit. The distance to TP is the same as the initial SL. 2% of equity / available margin is intended to be used each trade.
This is my code for calculating lot size:
There has been no problem using the EA on US share cfds, currencies or cryptos. I've only been doing demo trading with this.
What can I do so the EA doesn't allocate lot size differently to AUS share cfds as with other instruments?
Thanks.