Rejoindre la communauté
banner_forum
Devenez membre de la plus grande
communauté francophone sur le Forex
Partagez, échangez et apprenez en gagnant des crédits sur votre compte de trading

Comment on fait en MQL pour ...

  • furynick

    Tout est dans le titre.
    Code
    PriceAsk = NormalizeDouble(Ask, Digits);
  • Lorka85

    Merci de ta présence et rapidité Fury, je ne vais pas trop abusé de ta sympathie aujourd’hui :)

    j'avais essayer normalizedouble, mais ca arrondi en mettant des zero, pas en supprimant les chiffres après la décimal comme el fait DoubleToStr.
    dans mon exemple donc :

    buytp = NormalizeDouble(MarketInfo(Symbol(), MODE_ASK),5);

    ça donne : 1.44152000 alors que j'aimerais le prix 5 digits 1.44152

    peu etre une astuce avec reconversion strtodouble mais bon c'est curieux
  • furynick

    Là je comprends pas, quel est l'intérêt de supprimer des 0 sur un double ???
    Si tu ne veux pas les afficher tu utilises DoubleToStr et basta ?8-0

    Un double qui contient 1.44152000000000000000 contient donc 1.44152 ... il n'y a rien d'anormal.
  • Lorka85

    ha autant pour moi, donc dans un passage d'ordre les 0000 seront pas prit en comptes par ordersend ! merci
  • furynick

    Pour le passage d'ordres il est déjà préférable de ne pas mettre les SL/TP dans OrderSend mais de les passer après l'ouverture de la position avec un OrderModify. Ensuite, c'est effectivement une bonne idée d'utiliser le NormalizeDouble(value, Digits) pour les valeurs de prix dès lors que l'on utilise pas les variables prédéfinies Bid et Ask.
  • NYKOES

    J'ai un casse-tête actuel :

    "At placing of a pending order, the open price cannot be too close to the market. The minimal distance of the pending price from the current market one in points can be obtained using the MarketInfo() function with the MODE_STOPLEVEL parameter. In case of false open price of a pending order, the error 130 (ERR_INVALID_STOPS) will be generated." = issue de la doc MQL4.

    Effectivement, à l'envoi de mes pending orders, j'ai souvent ce genre d'erreur et cela remet en cause la fonctionnalité complète de mon EA. Je place mes orders comme ceci :

    Code
    double spread = (MarketInfo(Symbol(), MODE_SPREAD)); if (!IsTradeContextBusy() && IsTradeAllowed()) { OrderSend(Symbol(), OP_BUYSTOP, LOTS, High[1], 3, (Low[1] - (spread * Point * MathPow(0.1, Digits % 2)) - (3 * Point * MathPow(10, Digits % 2))), Ask + TP * Point * MathPow(10, Digits % 2), NAME, MAGICNUMBER, 0, Green); } if (!IsTradeContextBusy() && IsTradeAllowed()) { OrderSend(Symbol(), OP_SELLSTOP, LOTS, Low[1], 3, (High[1] + (spread * Point * MathPow(0.1, Digits % 2)) + (3 * Point * MathPow(10, Digits % 2))), Bid - TP * Point * MathPow(10, Digits % 2), NAME, MAGICNUMBER, 0, Red); } }

    Ma question est comment dois-je modifier les codes de pending orders ci-dessus en tenant compte de ce fameux "minimal distance" ?! merci par avance.


  • furynick

    Déjà, tu peux commencer par définir une variable
    Code
    double pip2point = Point * MathPow(10, Digits % 2);
    Ca évitera les erreurs et ça simplifiera le code en plus de l'accélérer (moins de calcul, moins d'appel de sous-fonction).

    Ensuite tu calcules le prix d'achat/vente et les SL/TP en dehors des OrderSend, le code sera plus lisible et plus facile à débugger (un Print avant l'OrderSend).
    Code
    price = High[1]; // ou Low[1] pour SELLSTOP stopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point; spread = MarketInfo(Symbol(), MODE_SPREAD) * Point; if (price < Ask + stopLevel) // ou (price > Bid - stopLevel) pour SELLSTOP price = Ask + stopLevel; // ou Bid - stopLevel pour SELLSTOP tp = price + TP * pip2point; // ou mieux encore, TP = TakeProfit * pip2point dans le init et où TakeProfit est le paramètre de l'EA ce qui évite une opération superflue ; pour un SELLSTOP on a price - TP sl = Low[1] - spread - 3 * pip2point; // ou High[1] + spread + 3 * pip2point; Print ("Trying to open buy stop order with price=", price, " sl=", sl, " and tp=", tp); ticket = OrderSend(Symbol(), OP_BUYSTOP, LOTS, price, 3, sl, tp, NAME, MAGICNUMBER, 0, Green); }

    En espérant que ça aide

    Pour rappel (et si je dis pas de conneries) :
    BUYSTOP : le cours actuel doit être inférieur au prix d'achat
    SELLSTOP : le cours actuel doit être supérieur au prix de vente
    BUYLIMIT : le cours actuel doit être supérieur au prix d'achat
    SELLLIMT : le cours actuel doit être inférieur au prix de vente

  • furynick

    En fait il y avait plusieurs erreurs dans ton code :
    tu convertissais le MarketInfo ModeSpread en je ne sais pas quoi alors qu'il est déjà en points (par ex. 31 sur EURCHF chez Vantage FX sur 5 digits). Il faut donc multiplier par Point sans plus et je pense que les erreurs de passage d'ordre provenait de là.
    Ensuite tu ne faisais pas de vérification de la validité de ton prix par rapport aux limites imposées par le broker, s'il y a un gap à l'ouverture de la nouvelle bougie l'ordre ne passe pas car il n'est dans les limites.

    Enfin, ce n'est pas une erreur mais un conseil, essaie de découper les étapes et ne pas tout faire sur une ligne (et c'est moi qui dit ça ... va falloir que j'aille vérifier si les poules n'auraient pas de dents), c'est plus lisible et plus facile à débugger.
  • NYKOES

    Merci Fury, je suis d'accord pour externaliser les TP,SL, etc. en variable interne, c'est forcément plus lisible, mais j'ai écris le code de cette façon pour bien comprendre ce que je faisais. Pour ce qui est de la conversion du spread, je vais voir si c'est bien ça qui ne fonctionne pas... ;)
  • NYKOES

    Eureka Fury ! Tout fonctionne à merveille maintenant en BT. Merci.

    Par contre, j'ai essayé d'instaurer un TrailingStop sur mon TP maintenant, et j'ai sans arrêt également ce fameux Ordermodify error 130 ...

    Code
    //----Trailing Stop for (int i = 0; i < OrdersTotal(); i++){ OrderSelect(i, SELECT_BY_POS, MODE_TRADES); //--- LONG TRADES if(OrderType() == OP_BUY && OrderSymbol() == Symbol() && OrderMagicNumber() == MAGICNUMBER){ if (Bid - OrderOpenPrice() >= TrailingStop * pip2point){ if (OrderStopLoss() < Bid - TrailingStop * pip2point || OrderStopLoss() == 0){ OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStop * pip2point, OrderTakeProfit(), Red); } } } //---SHORT TRADES if(OrderType() == OP_SELL && OrderSymbol() == Symbol() && OrderMagicNumber() == MAGICNUMBER){ if(OrderOpenPrice() - Ask >= TrailingStop * pip2point){ if((OrderStopLoss() > Ask + TrailingStop * pip2point) || OrderStopLoss() == 0){ OrderModify(OrderTicket(), OrderOpenPrice(),Ask + TrailingStop * pip2point, OrderTakeProfit(), Red); } } } }

  • furynick

    Théoriquement ça devrait fonctionner, moi j'aurais écrit le TS comme ça mais c'est exactement pareil :
    Code
    //----Trailing Stop int cnt = OrdersTotal(); // préférable d'utiliser une variable pour éviter les appels à la fonction à chaque boucle for (int i = 0; i < cnt; i++) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { // vérification de sélection, on ne sait jamais //--- LONG TRADES if(OrderSymbol() == Symbol() && OrderMagicNumber() == MAGICNUMBER) { // une seule vérification par boucle au lieu de 2 if(OrderType() == OP_BUY) { if (Bid >= OrderOpenPrice() + TrailingStop * pip2point) { if (OrderStopLoss() < Bid - TrailingStop * pip2point || OrderStopLoss() == 0) { OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStop * pip2point, OrderTakeProfit()); // pas de couleur pour les OrderModify pour éviter de surcharger le graphique } } } //---SHORT TRADES if(OrderType() == OP_SELL) { if(Ask <= OrderOpenPrice() - TrailingStop * pip2point) { if((OrderStopLoss() > Ask + TrailingStop * pip2point) || OrderStopLoss() == 0) { OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TrailingStop * pip2point, OrderTakeProfit()); } } } } } }
  • aymeric78

    Bonjour à tous
    Je m'initie à la programmation et je rencontre un petit problème, mon robot consiste à faire croiser 2 variables mais le problème c'est que quand ça se croise ça ouvre 4 positions et elle ne se ferme jamais, moi je voulais que quand les 2 variables se croisent ça ferme l'ancienne position par exemple à l'achat et ouvre une nouvelle position par exemple à la vente.

    Pouvez vous m'aider svp ?
  • furynick

    Salut aymeric,

    ta question est un peu vague et limite il faudrait développer un EA complet pour y répondre.
    Peux-tu au moins soumettre ton code pour qu'on (je ?) puisse comprendre ce que tu veux faire et corriger tes erreurs sur un cas concret ?
  • aymeric78

    Merci furynick de me répondre.
    Voici mon code, je pense que c'est par rapport au refresh et ça se croise plusieurs fois.
    Code
    //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- return(0); } int start() // Special fonct. start { double ma_expo=iMA(NULL,0,5,0,MODE_EMA,PRICE_CLOSE,0); double ma_simple=iMA(NULL,0,14,0,MODE_SMA,PRICE_CLOSE,0); int ticket; if(ma_expo==ma_simple) { Alert("croisement"); Print("croisement"); } if(DoubleToStr(ma_expo,6)==DoubleToStr(ma_simple,6)) { /*Alert("croisement 2 script 1"); Alert("ma expo= ", DoubleToStr(ma_expo,8)); Alert("ma simple= ", DoubleToStr(ma_simple,8)); Print("croisement 2"); Print(GlobalVariableGet("ma expo")); Print(GlobalVariableGet("ma simple"));*/ if(GlobalVariableGet("ma expo")<GlobalVariableGet("ma simple")) { ticket = OrderSend(Symbol(),OP_BUY,1,Ask,1,0,0,NULL,1234,0,Blue); Print("ticket ", ticket); /*while (ticket == -1) // tant que l’ordre n’est pas passé { Sleep(1000); // on attend une seconde RefreshRates(); //on rafraichit les valeurs du cours de la paire //ticket = OrderSend(Symbol(),OP_BUY,0.1,1000,1,0,0,NULL,1234,0,Blue); ticket=OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, Bid-15*Point, Bid+15*Point, "Premier ordre achat !", 1); } Alert("stop level:",MarketInfo("EURUSD",MODE_STOPLEVEL)); if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25) { ticket=OrderSend(Symbol(), OP_BUY,1, Ask, 3, Ask-25*Point, 0, "Premier ordre achat !", 16384,0,Green); /* while (ticket == -1) // tant que l’ordre n’est pas passé { Sleep(1000); // on attend une seconde RefreshRates(); //on rafraichit les valeurs du cours de la paire ticket = OrderSend(Symbol(), OP_BUY,1, Ask, 3, Ask-MarketInfo("EURUSD",MODE_STOPLEVEL)*Point, Ask+MarketInfo("EURUSD",MODE_STOPLEVEL)*Point, "Premier ordre achat !", 16384,0,Green); } Print("test ask",Ask-50*Point); Print("ticket ", ticket); //if(ticket<0) // { Print("OrderSend failed with error #",GetLastError()); //} }*/ Alert("Acheter"); } if(GlobalVariableGet("ma expo")>GlobalVariableGet("ma simple")) { ticket = OrderSend(Symbol(),OP_SELL,1,Bid,1,0,0,NULL,1234,0,Blue); Print("ticket ", ticket); /* while (ticket == -1) // tant que l’ordre n’est pas passé { Sleep(1000); // on attend une seconde RefreshRates(); //on rafraichit les valeurs du cours de la paire //ticket = OrderSend(Symbol(),OP_SELL,0.1,1000,1,0,0,NULL,1234,0,Blue); */ /*if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25) { ticket =OrderSend(Symbol(), OP_SELL, 0.1, Bid, 3, Bid-MarketInfo("EURUSD",MODE_STOPLEVEL)*Point,0, "Premier ordre vente !", 16384,0,Green); /*while (ticket == -1) // tant que l’ordre n’est pas passé { Sleep(1000); // on attend une seconde RefreshRates(); //on rafraichit les valeurs du cours de la paire ticket = OrderSend(Symbol(), OP_SELL, 0.1, Ask, 3, Ask-MarketInfo("EURUSD",MODE_STOPLEVEL)*Point, Ask+MarketInfo("EURUSD",MODE_STOPLEVEL)*Point, "Premier ordre vente !", 16384,0,Green); } Print("ticket ", ticket); //if(ticket<0) //{ Print("OrderSend failed with error #",GetLastError()); //} } //} Print("ticket ", ticket);*/ Alert("Vendre"); } } /*int tic; tic=OrderSend(Symbol(),OP_BUY,1,Ask,3,Ask-25*Point,Ask+25*Point,"My order #2",16384,0,Green); Print("tic : ", tic); /*Alert("ma1= ", DoubleToStr(ma_expo,8)); Alert("ma2= ", DoubleToStr(ma_simple,8));*/ /*Print ("ma simple= ", DoubleToStr(ma_simple,8)); Print("ma expo ", DoubleToStr(ma_expo,8));*/ //Print("gb", DoubleToStr(GlobalVariableGet("ma expo"),8)); GlobalVariableSet("ma simple", ma_simple); GlobalVariableSet("ma expo", ma_expo); return(0); }
  • furynick

    J'ai édité le post pour ajouter les balises [ code ] [ / code ] pour qu'il soit plus lisible et je me suis permis de supprimer ta remarque Nykoes, j'espère que tu ne m'en voudra pas ;)

    Aymeric, pour te répondre c'est très simple, tu n'utilises pas la bonne procédure.

    Pour détecter un croisement il faut que tu récupères les valeurs des deux dernières barres complètes :
    Code
    double ma_expo=iMA(NULL,0,5,0,MODE_EMA,PRICE_CLOSE,1); double ma_simple=iMA(NULL,0,14,0,MODE_SMA,PRICE_CLOSE,1); double ma_expo_avant=iMA(NULL,0,5,0,MODE_EMA,PRICE_CLOSE,2); double ma_simple_avant=iMA(NULL,0,14,0,MODE_SMA,PRICE_CLOSE,2); bool buy, sell;

    Ensuite tu compares les valeurs entre elles :
    Code
    if (ma_expo_avant > ma_simple_avant && ma_expo < ma_simple) sell = true; if (ma_expo_avant < ma_simple_avant && ma_expo > ma_simple) buy = true;

    De plus, pour n'avoir qu'une seule ouverture tu dois utiliser la fonction de vérif d'une nouvelle barre que j'ai publié sur le forum
    Code
    //+------------------------------------------------------------------+ //| detect new bar formed | //+------------------------------------------------------------------+ double savedVolume; bool newBarFormed() { double vol = iVolume(Symbol(), Period(), 0); bool ret = vol < savedVolume; savedVolume = vol; return(ret); } int init () { savedVolume = iVolume(Symbol(), Period(), 0); } int start () { // placer la vérification des signaux ici if (newBarFormed()) { if (buy) { // code d'achat ici } if (sell) { // code de vente ici } } }
  • aymeric78

    J'ai encore un problème, quelle est le moyen de récuperer la valeur du ticket de l'ordre passer pour fermer avec l'OrderClose ?

    Merci de votre de réponse.
  • furynick

    si tu n'as qu'un seul ordre par paire tu peux stocker le ticket dans une variable globale, sinon il faut faire une boucle de OrderTotals() itérations et un OrderSelect à chaque.

    Je t'invite à consulter les nombreux codes sources sur codebase.mql4 qui t'aideront à faire tes premiers pas. ainsi que docs.mql4.com pour la documentation du langage qui est simplissime par rapport à d'autres langages.
    Sans oublier les ressources MT4 de Forexagone :)

    Ce topic à pour but de répondre à des questions précises sur des problèmes particuliers de codage ou d'algo et non pas à apprendre à coder ;)
  • Weakifix (invité)

    Bonsoir,

    Voila je me lance a programmé mon premier EA ... génial ... mais je suis une quiche ... ( 300 page plus tard )

    La question est:

    Je ne trouve pas le moyen d'utiliser les niveaux (Bullish est bearish ) de Williams Percent Range dans mon petit robot pour lui donner ordre d'acheter, vendre ou tout simplement ne pas confirmer un ordre.

    Merci pour votre aide qui sera certainement trés précieuse.
  • Lorka85

    weakifi, sur quoi tu veut te basé pour que le percent range donne un ordre buy ?


    sinon j'ia un petit soucis avec ce code de breakeven, stopeven, uniquement sur les pairs au format eur/usd, gbp/usd (1.44000) mais ça marche impecable sur les pairs asiatique (au fomat 170.58)

    extrait en question pour les ordre BUY
    Code
    if (OrderType()==OP_BUY) { if (OrderStopLoss()==0) { OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-StopLoss*Point,OrderOpenPrice()+TakeProfit*Point,0,LightGreen); return(0); } //---- StopEven if (StopEven == true ) { if (OrderStopLoss()!=OrderOpenPrice()-Point*StopLoss/StopEvenDivisedBy && OrderStopLoss()!=OrderOpenPrice()) { if (Bid-OrderOpenPrice()>Point*StopEvenAt&&OrderStopLoss()<OrderOpenPrice()&&Bid-OrderOpenPrice()<Point*BreakEvenAt) { {OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-Point*StopLoss/StopEvenDivisedBy,OrderTakeProfit(),0,LightGreen); return(0);} } } } //---- BreakEven if (BreakEven == true) { if (OrderStopLoss()!=OrderOpenPrice()) { if (Bid-OrderOpenPrice()>Point*BreakEvenAt&&OrderStopLoss()<OrderOpenPrice()) { {OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice(),OrderTakeProfit(),0,LightGreen); return(0);} } } } }

    en gros sur les pairs au format eur/usd, ca me fait n'improte quoi, le stopeven (stoploss divisé par 2 si X pips franchis) se rabat, s'enleve, le breakeven est a +5 pips du pris d'entré, puis a - 5 pips.... il y a un truc a voir au niveau de POINT ? pour que ca sois compatible avec tous les format de pairs ?

    merci
  • furynick

    Boudu ... pas étonnant que les bugs soient bien cachés dans tout ce fouilli (et encore je reste poli ;) ), ça sert à quoi le double bloc d'expression ????
    Code
    if (toto) { { var=0; } }

    Etape 1 : écrire un code propre (respecter l'indentation)
    Etape 2 : écrire proprement sont code (aérer avec des espaces après la ponctuation et autour des opérations)
    Etape 3 : mettre au propre le code qu'on écrit (commenter - bon, là j'avoue c'est l'hôpital qui se fout de la charité)
    Etape 4 : le code doit s'écrire proprement (limiter la taille des lignes)

    Aller, je file un petit coup de pouce : http://tools.arantius.com/tabifier ... idéalement remplacer les tabulations par 2 espaces pour la lisibilité et la portabilité.

    Tant que j'y suis, inutile d'utiliser les égalités sur les variables booléennes.

    Code
    if (BreakEven == true) est strictement identique à
    Code
    if (BreakEven) ou l'inverse
    Code
    if (BreakEven != true || BreakEven == false) est strictement identique à
    Code
    if (!BreakEven)

    Et pour finir, les lignes de codes qui comportent plus de 4 à 5 instructions contiendront potentiellement autant de bug, ton problème vient certainement de là. Essaie de scinder les lignes en remplaçant les
    Code
    if (toto && tata) par
    Code
    if (toto) if (tata) et ajouter des Print à chaque étape pour débugger et comprendre ce que fait l'EA.