Hallo, ich möchte meine Lot-Größe pro Trade berechnen, dass ich mit einem SL von 250pip max. 2% riskiere. Dafür habe ich folgendes versucht:
sl_distance ist input int inp_SL_points = 250; und wird (wieso auch immer) beim Aufruf als 0,0025 dargestellt, deshalb *100000 um auf 250 zu kommen.
Das Problem ist jetzt, dass die Lotgröße zu klein berechnet wird. Bei meinem Demo mit 10000€ hätte ich ein allowedRisk von 200€, bei einem Test von EURUSD, wurde mir für den Einsatz 0.09Lot berechnet. Allerdings ist das nur ein Risiko von ~37€. Bei einem SL von 250Pip könnte ich ~0,86 Lot setzen. Muss man in das ganze den Hebel noch mit einbauen und wenn ja wie? Oder habe ich einen anderen Fehler?
schau, da hast eine Berechnung was passt, die Funktioniert fast überall
enum ENUM_RISIKO_TYPE //wird mit zusammen mit dem Risiko verwendet { FixLots, // 0 = Fixlots werden eingetragen Geldbetrag, // 1 = Gegenwert in Geld wird eingetragen Prozent, // 2 = Risiko in Prozent wird eingetragen GridGeldwert, // 3 = Grid, in verwendung mit dem Grid multiplier und der max Trade anzahl GridProzent, // 4 = % von Account Size über alle Max Orders eines Grids Margin // 5 = Prozent der vorhandenen Margin }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double Risikoberechnung(const string symbol, const double risiko, const double stoploss, const int Risikotype, const int Grid = 0, const int MaxOrder = 0) { double lots = 0; double Geldrisiko = 0; double openline = ObjectGetDouble(0,"BuySellLine",OBJPROP_PRICE); double stopline = ObjectGetDouble(0,"StopLine",OBJPROP_PRICE); switch(Risikotype) { case FixLots: // 0 = FixLots { lots = risiko; return(NearestLot(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))); } case Geldbetrag: // 1 = Geldbetrag { if(stoploss == 0) { Print("You have to enter a StopLoss"); break; } else lots = NormalizeDouble(risiko / (stoploss * _sym.TickValue()), 2); // Geldrisk / (SL in Pips * Tickvalue) return(NearestLot(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))); } case Prozent: // 2 = Prozent { if(Kapital == 0) Geldrisiko = _account.Balance() / 100 * risiko; // Riskio in Geldwert else Geldrisiko = Kapital /100 *risiko; if(stoploss == 0) { Print("You have to enter a StopLoss"); break; } else { if(_sym.TradeCalcMode() == SYMBOL_CALC_MODE_FOREX) { lots = Geldrisiko / (stoploss * _sym.TickValue()); //Print(Geldrisiko," ",stoploss, " ", _sym.TickValue()); } if(_sym.TradeCalcMode() != SYMBOL_CALC_MODE_FOREX && SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE) == "USD" ) lots = Geldrisiko / (_sym.ContractSize() * MathAbs(stopline-openline)*(1/SymbolInfoDouble("EURUSD",SYMBOL_BID))) ; if(_sym.TradeCalcMode() != SYMBOL_CALC_MODE_FOREX && SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE) != "USD" ) lots = Geldrisiko / (_sym.ContractSize() * MathAbs(stopline-openline)) ; //Print("lots: ", lots, " Geld: ", Geldrisiko, " Stop: ", stoploss, " Tick: ", _sym.TickValue()); } return(NearestLot(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))); } case GridGeldwert: // Grid Risiko Geldwert { lots = (risiko * SymbolLeverage) / _sym.ContractSize(); return(NearestLot(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))); } case GridProzent: // Grid Risiko { // Anzahl der offenen Grideinheiten f(x) = n*(n+1) / 2 ; n = Anzahl der order, für max Calc einfach die 30 nehmen double _SL = ((MaxOrder * (MaxOrder + 1)) / 2) * Grid; // Mathematik, Dreieckfunktion für die Berechnung if(Kapital == 0) Geldrisiko = _account.Balance() / 100 * risiko; // Riskio in Geldwert else Geldrisiko = Kapital/100*risiko; lots = NormalizeDouble(Geldrisiko / (_SL * _sym.TickValue()), 2); // Geldrisk / (SL in Pips * Tickvalue) return(NearestLot(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))); } case Margin: // Margin Risiko { double Lot1 = 0, fullmargin = 0, MarginRate = 0, AccountSize = 0; if(Kapital == 0) fullmargin = (_account.Balance() * SymbolLeverage); else fullmargin = Kapital*SymbolLeverage; if(_sym.TradeCalcMode() == SYMBOL_CALC_MODE_FOREX) lots = NormalizeDouble(fullmargin / _sym.ContractSize() / 100 * risiko, 2); if(_sym.TradeCalcMode() == SYMBOL_CALC_MODE_CFD) { double margin; MarginInit(ORDER_TYPE_BUY, symbol, margin); lots = NormalizeDouble(((fullmargin / 100 * risiko) * SymbolLeverage) / (_sym.ContractSize() * Trade.Bid * margin), 2); } return(NearestLot(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))); if(_sym.TradeCalcMode() == SYMBOL_CALC_MODE_CFDLEVERAGE) { double margin; MarginInit(ORDER_TYPE_BUY, symbol, margin); lots = (_sym.ContractSize() * Trade.Bid) / ((fullmargin/100*risiko)*SymbolLeverage*MarginRate); } return(NearestLot(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP))); /*have to be done if(_sym.TradeCalcMode() == SYMBOL_CALC_MODE_CFDINDEX) { double margin; MarginInit(ORDER_TYPE_BUY, symbol, margin); //Margin: (Lots * ContractSize * MarketPrice) * TickPrice / TickSize * Margin_Rate lots = (_sym.ContractSize() * Trade.Bid) / (risiko*SymbolLeverage*MarginRate); } return(LotStep(lots)); */ } } return(lots); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool MarginInit(const ENUM_ORDER_TYPE action, const string symbol, double &margin) // Initial Margin Return aus der Symbol Info { double MarginInit, MarginMain; const bool Res = SymbolInfoMarginRate(symbol, action, MarginInit, MarginMain); margin = Res ? MarginInit : 0; return(Res); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double NearestLOLot(double v, double to) { double value = 0; value = to * MathFloor(v / to); double min = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); double max = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX); if(value < SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)) value = min; if(value > SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX)) value = max; return(value); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double NearestHILot(double v, double to) { double value = 0; value =to * MathCeil(v / to); double min = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); double max = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX); if(value < SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)) value = min; if(value > SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX)) value = max; return(value); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double NearestLot(double v, double to) { double value = 0; value =to * MathRound(v / to); double min = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); double max = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX); if(value < SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)) value = min; if(value > SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX)) value = max; return(value); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+
schau, da hast eine Berechnung was passt, die Funktioniert fast überall
Ich habe die jetzt als Include gespeichert, ist das richtig? Denn da kriege ich ne riesen Liste Fehlermeldungen (siehe Bild im Anhang)
Ich habe die jetzt als Include gespeichert, ist das richtig? Denn da kriege ich ne riesen Liste Fehlermeldungen (siehe Bild im Anhang)
gut da hab ich dir noch was verheimlicht ;-)
dachte du bist schon weiter
du brauchst die CTrade Klassen, musst du einfügen, dann hast du gleich mal 95% weg
#include <Trade\Trade.mqh> CTrade _trade; // wird verwendet für die Trade Funktionen
#include <Trade\AccountInfo.mqh> CAccountInfo _account; // wird verwendet für die Account Information Funktionen
#include <Trade\SymbolInfo.mqh> CSymbolInfo _sym;
dann hab ich da noch was neu gemacht, hatte ich ganz vergessen
das gehört in die OnTick, gleich ganz am Anfang
Trade.Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK); Trade.Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
das in den Globalen Bereich
struct SymbolInfos { double Ask; double Bid; }; SymbolInfos Trade;
und Kapital ist ein Eingabeparameter
da gehört
input double Kapital = 5000; // 0 = full account Balance
Der ist dafür da, wenn Du als Tradingkapital als beispiel 5k hast, du am Konto aus Sicherheitsgründen nur 1k, dann kann man da das gesamtkapital eintragen, bin ja ein fauler hund
dann hab ich noch, das liegt aber nur an der Krücke MT5, weil für die ESMA rules kann MT5 nur dem Konto eine Leverage zuordnen, aber nicht dem Symbol, in der Leverage berechnung beim Broker schaut das anders aus, darum hab ich das als Eingabeparameter gemacht, zb EURUSD = 1:30 und GBPJPY ist ja nur 1:20 (auch broker abhängig) aber im MT steht immer 1:30, da er das für das Symbol nicht einzeln zuweisen kann
input int SymbolLeverage = 400; // Leverage da keine mql info vorhanden ist
zur Erklärung
double Risikoberechnung(const string symbol, const double risiko, const double stoploss, const int Risikotype, const int Grid = 0, const int MaxOrder = 0)
symbol sollte klar sein
risiko - je nach Enum Wert ist das Prozent, Geld oder Margin.
stoploss - unbeding tin Points
Risikotype aus der ENU;
die restlichen 2 sind nur bei Gridrisiko in verwendung
im EA sieht das dann so aus, gerade getestet, du musst nur den Namen vom include für die Risikoberechnung anpassen
//+------------------------------------------------------------------+ //| test333.mq5 | //| Copyright 2020, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ struct SymbolInfos { double Ask; double Bid; }; SymbolInfos Trade; #include <11_Risiko_Berechnung.mqh> // fix lots, Fixer Betrag oder auch Prozent #include <Trade\Trade.mqh> CTrade _trade; // wird verwendet für die Trade Funktionen #include <Trade\AccountInfo.mqh> CAccountInfo _account; // wird verwendet für die Account Information Funktionen #include <Trade\DealInfo.mqh> CDealInfo _deal; // wird verwendet für die Deal Information Funktionen #include <Trade\HistoryOrderInfo.mqh> CHistoryOrderInfo _historyorder; // wird verwendet für die Order History Informationen #include <Trade\OrderInfo.mqh> COrderInfo _order; // wird verwendet für die Order Information Funktionen #include <Trade\PositionInfo.mqh> CPositionInfo _position; // wird verwendet für die Position Information Funktionen #include <Trade\SymbolInfo.mqh> CSymbolInfo _sym; // wird verwendet für die Symbol Information Funktionen #include <Trade\TerminalInfo.mqh> CTerminalInfo _terminal; // wird verwendet für die Symbol Information Funktionen input ENUM_RISIKO_TYPE Risikoart; // Default Wert, wird verwendet für die Risikokalkulation, include 11_Risiko_Berechnung input group "Risiko"; input double Risiko = 2; input double Kapital = 5000; // 0 = full account Balance input int SymbolLeverage = 400; // Leverage da keine mql info vorhanden ist input double StopLoss = 2000; int OnInit() { //--- _sym.Name(_Symbol); // Initialisieren des Symbols, für die CSymbol _sym.RefreshRates(); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { Trade.Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK); Trade.Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); Print(Risikoberechnung(_Symbol,Risiko, StopLoss,Prozent)); } //+------------------------------------------------------------------+
Joa... ich glaube, da hattest du meine Fähigkeiten noch etwas überschätzt xD
Aus irgend einem Grund rechnet der aber immer mit 5000 als Kapital, ob ich da 0 oder 10000 eingebe, woran liegt das?
Joa... ich glaube, da hattest du meine Fähigkeiten noch etwas überschätzt xD
Aus irgend einem Grund rechnet der aber immer mit 5000 als Kapital, ob ich da 0 oder 10000 eingebe, woran liegt das?
Hallo,
bist Du dir sicher?
Das würde der Bedingung widersprechen
if(Kapital == 0) Geldrisiko = _account.Balance() / 100 * risiko; // Riskio in Geldwert else Geldrisiko = Kapital /100 *risiko;
bei 0 nimmt er deine Account Balace (vielleicht ist die gerade 5000)
sonst nimmt er den Wert
und dann rechnet er ja weiter mit dem Wert
if(_sym.TradeCalcMode() == SYMBOL_CALC_MODE_FOREX) { lots = Geldrisiko / (stoploss * _sym.TickValue()); //Print(Geldrisiko," ",stoploss, " ", _sym.TickValue()); }
Du kannst Dir aber nach der Geldrisiko Berechnung mal eine
Print("Geldrisiko: ", Geldrisiko);
ausgeben und schauen was er nimmt.
es könnte natürlich auch sein, das dein Broker wieder was eigenes erfunden hat und die Kalkulation nicht auf Forex Basis macht, das steht im Symbol
aber sonst würde mir da nix einfallen
Ich mache das als Backtest und gebe als Startkapital 10.000 an, in den Spezifikationen steht Forex. Ich habe nur grade festgestellt, dass wohl mein meta trader7editor spinnt und wenn ich neu kompeliere, trotzdem die alte Version genommen wird, keine Ahnung wieso und ob das das Problem ist.
Bei der Geldrisikoberechnung kommt 100 raus, bei 2% also auch 5000
Ich mache das als Backtest und gebe als Startkapital 10.000 an, in den Spezifikationen steht Forex. Ich habe nur grade festgestellt, dass wohl mein meta trader7editor spinnt und wenn ich neu kompeliere, trotzdem die alte Version genommen wird, keine Ahnung wieso und ob das das Problem ist.
Bei der Geldrisikoberechnung kommt 100 raus, bei 2% also auch 5000
Und was kommt raus wenn du bei kapital 0 eingibst? Dann müsste er das von deiner account size nehmen, was er sicher auch tut
Und was kommt raus wenn du bei kapital 0 eingibst? Dann müsste er das von deiner account size nehmen, was er sicher auch tut
nun... da kommt auch 5000 raus, meinst du kannst mal drüber schauen, ob ich das was dopple oder so?
#property strict; struct SymbolInfos { double Ask; double Bid; }; SymbolInfos Trade; //+------------------------------------------------------------------+ #include <Risikoberechnung/Risikoberechnung.mqh> // fix lots, Fixer Betrag oder auch Prozent //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> CTrade _trade; // wird verwendet für die Trade Funktionen //+------------------------------------------------------------------+ #include <Trade\AccountInfo.mqh> CAccountInfo _account; // wird verwendet für die Account Information Funktionen #include <Trade\DealInfo.mqh> CDealInfo _deal; // wird verwendet für die Deal Information Funktionen #include <Trade\HistoryOrderInfo.mqh> CHistoryOrderInfo _historyorder; // wird verwendet für die Order History Informationen #include <Trade\OrderInfo.mqh> COrderInfo _order; // wird verwendet für die Order Information Funktionen #include <Trade\PositionInfo.mqh> CPositionInfo _position; // wird verwendet für die Position Information Funktionen #include <Trade\SymbolInfo.mqh> CSymbolInfo _sym; // wird verwendet für die Symbol Information Funktionen #include <Trade\TerminalInfo.mqh> CTerminalInfo _terminal; // wird verwendet für die Symbol Information Funktionen //+------------------------------------------------------------------+ input group "GENERAL" input ENUM_TIMEFRAMES inp_Timeframe = PERIOD_CURRENT; // timeframe input ENUM_APPLIED_PRICE inp_applied_price = PRICE_CLOSE; // type of price input group "MONEY" input double inp_Lotsize = 1.00; // Lotsize input int inp_SL_points = 250; // SL (points) input int inp_TP_points = 400; // TP (points) //+------------------------------------------------------------------+ //| Indicators | //+------------------------------------------------------------------+ input group "MACD" input int inp_fast_ema_period = 12; // period of fast ema input int inp_slow_ema_period = 26; // period of slow ema input int inp_signal_period = 9; // period of signal input group "MA" input int inp_ema_period = 200; // period of ema input int inp_ema_shift = 0; // ema shift input ENUM_MA_METHOD inp_ma_method = MODE_EMA; // ma mode //+------------------------------------------------------------------+ input group "Risiko"; input ENUM_RISIKO_TYPE Risikoart; // Default Wert, wird verwendet für die Risikokalkulation, include RisikoBerechnung input double Risiko = 2; input double Kapital = 0; // 0 = full account Balance input int SymbolLeverage = 400; // Leverage da keine mql info vorhanden ist //+------------------------------------------------------------------+ input double StopLoss = 250; //+------------------------------------------------------------------+ //Price MqlRates rates[]; // umbenannt von price -> rates //MACD int haMACD; double buMACD_Buffer[]; double buMACD_Signal[]; int toCopy = 3; int precision = _Digits+1; //EMA int haEMA; double buEMA_buffer[]; //--- Einfügen einer neuen Variablen (Wert in Sekunden für eine Kerze dieses Zeitrahmens, für М15 wäre es 60 sec. * 15 = 900 sec) datetime Time_open = 60 * _Period; //--- Einfügen einer neuen Variablen (Eröffnungszeitpunkt der Kerze des 1. Position) datetime Time_bar = 0; double sl_distance; double tp_distance; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { _sym.Name(_Symbol); // Initialisieren des Symbols, für die CSymbol _sym.RefreshRates(); ArraySetAsSeries(rates, true); haMACD=iMACD(_Symbol,inp_Timeframe,inp_fast_ema_period,inp_slow_ema_period,inp_signal_period,inp_applied_price); if(haMACD==INVALID_HANDLE) { Alert("*ERROR* creating iMACD handle"); return(INIT_FAILED); } ArraySetAsSeries(buMACD_Buffer,true); ArraySetAsSeries(buMACD_Signal,true); haEMA = iMA(_Symbol, inp_Timeframe, inp_ema_period, inp_ema_shift, inp_ma_method, inp_applied_price); if(haEMA == INVALID_HANDLE) { Alert("*ERROR* creating iMA handle"); return(INIT_FAILED); } sl_distance=inp_SL_points*_Point; tp_distance=inp_TP_points*_Point; return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { Trade.Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK); Trade.Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); //+------------------------------------------------------------------+ if(CopyRates(Symbol(),inp_Timeframe,0,toCopy,rates) != toCopy) return; if(CopyBuffer(haMACD,0,0,toCopy,buMACD_Buffer) != toCopy) return; if(CopyBuffer(haMACD,1,0,toCopy,buMACD_Signal) != toCopy) return; if(CopyBuffer(haEMA, 0,0,toCopy,buEMA_buffer) != toCopy) return; //+------------------------------------------------------------------+ if(PositionsTotal() < 1) { if(buMACD_Buffer[0] < 0 && buMACD_Signal[0] < 0 && buMACD_Buffer[0] > buMACD_Signal[0] && buMACD_Buffer[1] <= buMACD_Signal[1] && rates[1].close > buEMA_buffer[1]) { double lotSize = Risikoberechnung(_Symbol, 2, 250, Prozent); lotSize = NormalizeDouble(lotSize, 2); Print(lotSize); Comment(Kapital); if(_trade.Buy(lotSize, NULL, Trade.Ask, (Trade.Ask-sl_distance), (Trade.Ask+tp_distance))) { Time_open = TimeCurrent()-rates[0].time; // speichert das Zeitintervall zwischen Kerzeneröffnung und Positionseröffnung Time_bar = rates[0].time; // speichert den Eröffnungszeitpunkt der Kerze der ersten Position } } else if(buMACD_Buffer[0] > 0 && buMACD_Signal[0] > 0 && buMACD_Buffer[0] < buMACD_Signal[0] && buMACD_Buffer[1] >= buMACD_Signal[1] && rates[1].close < buEMA_buffer[1]) { if(_trade.Sell(1, NULL, Trade.Bid, (Trade.Bid+sl_distance), (Trade.Bid-tp_distance))) { Time_open = TimeCurrent()-rates[0].time; // speichert das Zeitintervall zwischen Kerzeneröffnung und Positionseröffnung Time_bar = rates[0].time; // speichert den Eröffnungszeitpunkt der Kerze der ersten Position } } } } //+------------------------------------------------------------------+
nun... da kommt auch 5000 raus, meinst du kannst mal drüber schauen, ob ich das was dopple oder so?
Abgesehen davon, das du deine input variablen nochmals durchgehen solltest,
wenn da jetzt auch 5000 kommt, dann machst du den backtest mit 5000
anders geht sich das nicht aus
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Hallo, ich möchte meine Lot-Größe pro Trade berechnen, dass ich mit einem SL von 250pip max. 2% riskiere. Dafür habe ich folgendes versucht:
sl_distance ist input int inp_SL_points = 250; und wird (wieso auch immer) beim Aufruf als 0,0025 dargestellt, deshalb *100000 um auf 250 zu kommen.
Das Problem ist jetzt, dass die Lotgröße zu klein berechnet wird. Bei meinem Demo mit 10000€ hätte ich ein allowedRisk von 200€, bei einem Test von EURUSD, wurde mir für den Einsatz 0.09Lot berechnet. Allerdings ist das nur ein Risiko von ~37€. Bei einem SL von 250Pip könnte ich ~0,86 Lot setzen. Muss man in das ganze den Hebel noch mit einbauen und wenn ja wie? Oder habe ich einen anderen Fehler?