Pourquoi n'y a-t-il PAS d'évaluation complète de l'environnement dans la base de code ? - page 3

 
WHRoeder:
Voici le mien, sans la logique de négociation proprement dite.
J'ai reçu un message concernant le filtre jour/heure de négociation. La demande était de 1800-0600 du lundi au vendredi. Cela nécessite d'exclure 0-0600 le lundi et 1800-close le vendredi. Le code permettait le report des heures mais pas des jours. Amélioration :
    /*++++ Day/Time allowed to open*/{
    datetime    now = TimeGMT();
    //extern double   TradeHr.UTC.Start   =   7.3;    // London-1
    //extern double   TradeHr.UTC.End     =  12.9;    // NY open
    int secStart    = 3600*TradeHr.UTC.Start,
        secEnd      = 3600*TradeHr.UTC.End,
        hrBeg       = (now-secStart+86400)%86400,
        hrEnd       = (now-secEnd  +86400)%86400;
    if (hrBeg > hrEnd){ double Tminus=hrBeg/3600.-24;
                StrApnd(EA.status," HR", DoubleToStr(Tminus,2));    return; }
    // TradeHr: 0600-1800       1800-0600       1800-0600
    // TOD:     0600-1800       1800-2359       0000-0600
    // DOW:     DOW(today)      DOW(today)      DOW(yesterday)
    int         TOD = now % 86400;      // Time of the day
    datetime    BOD = now - TOD;        // Beginning of the day (today 0000z)
    if (TOD < secStart) int DOW = TimeDayOfWeek(BOD - 1);       // Yesterday.
    else                    DOW = TimeDayOfWeek(BOD),   /* https://www.mql5.com/en/forum/127483
            // reports DayOfWeek() always returns 5 in the tester. No refresh?*/
        int DayMask = 1 << DOW; // #define DAYS_MAX    0x3F// 1<<6-1=63. (S-F)
    //extern int      Days.Mask               =  55;      // Not Wed
    if ((Days.Mask & DayMask) == 0){  StrApnd(EA.status," Day=",DOW); return; }
    /*---- Day/Time allowed to open*/}
Et ma correction pour le commentaire de RaptorUK:
double  PointValuePerLot(string pair="") {
    /* Value in acnSum currency of a Point of Symbol.
     * In tester I had a sale: open=1.35883 close=1.35736 (0.00147)
     * gain$=97.32/6.62 lots/147 points=$0.10/point or $1.00/pip.
     * IBFX demo/mini       EURUSD TICKVALUE=0.1 MAXLOT=50 LOTSIZE=10,000
     * IBFX demo/standard   EURUSD TICKVALUE=1.0 MAXLOT=50 LOTSIZE=100,000
     *                                  $1.00/point or $10.00/pip.
     *
     * https://www.mql5.com/en/forum/127584 CB: MODE_TICKSIZE will usually return the
     * same value as MODE_POINT (or Point for the current symbol), however, an
     * example of where to use MODE_TICKSIZE would be as part of a ratio with
     * MODE_TICKVALUE when performing money management calculations which need
     * to take acnSum of the pair and the acnSum currency. The reason I use
     * this ratio is that although TV and TS may constantly be returned as
     * something like 7.00 and 0.00001 respectively, I've seen this
     * (intermittently) change to 14.00 and 0.00002 respectively (just example
     * tick values to illustrate). */
    if (pair == "") pair = Symbol();
    return(  MarketInfo(pair, MODE_TICKVALUE)
           / MarketInfo(pair, MODE_TICKSIZE) ); // Not Point.
}
 
WHRoeder:
Et ma correction pour le commentaire de RaptorUK:
J'ai renommé PointValuePerLot en DeltaValuePerLot puisque aCurrencyChange = aPriceChange * OrderSize() * DeltaValuePerLot(). J'ai également ajouté d'autres commentaires.
double  PipValuePerLot(string pair=""){ return(DeltaValuePerLot() * pips2dbl); }
double  DeltaValuePerLot(string pair=""){
    /* Value in account currency of a Point of Symbol.
     * In tester I had a sale: open=1.35883 close=1.35736 (0.0147)
     * gain$=97.32/6.62 lots/147 points=$0.10/point or $1.00/pip.
     * IBFX demo/mini       EURUSD TICKVALUE=0.1 MAXLOT=50 LOTSIZE=10,000
     * IBFX demo/standard   EURUSD TICKVALUE=1.0 MAXLOT=50 LOTSIZE=100,000
     *                                  $1.00/point or $10.0/pip.
     *
     * https://www.mql5.com/en/forum/127584 CB: MODE_TICKSIZE will usually return the
     * same value as MODE_POINT (or Point for the current symbol), however, an
     * example of where to use MODE_TICKSIZE would be as part of a ratio with
     * MODE_TICKVALUE when performing money management calculations which need
     * to take account of the pair and the account currency. The reason I use
     * this ratio is that although TV and TS may constantly be returned as
     * something like 7.00 and 0.0001 respectively, I've seen this
     * (intermittently) change to 14.00 and 0.0002 respectively (just example
     * tick values to illustrate).
     * https://www.mql5.com/en/forum/135345 zzuegg reports for non-currency DE30:
     * MarketInfo(Symbol(),MODE_TICKSIZE) returns 0.5
     * MarketInfo(Symbol(),MODE_DIGITS) return 1
     * Point = 0.1
     * Prices to open must be a multiple of ticksize */
    if (pair == "") pair = Symbol();
    return(  MarketInfo(pair, MODE_TICKVALUE)
           / MarketInfo(pair, MODE_TICKSIZE) ); // Not Point.
}
 
double  PipValuePerLot(string pair=""){ return(DeltaValuePerLot(pair) * pips2dbl); }
 
J'ai modifié le code de la polyligne pour permettre les superpositions, par exemple :
double  bottom      =         WindowPriceMin(),
        top         = MathMax(WindowPriceMax(), bottom+pips2dbl),// Div0
        topQuarter  = (3*top +   bottom)/4.,
        botQuarter  = (top   + 3*bottom)/4.;
int     iVisible    =           WindowFirstVisibleBar(),
        iVisEnd     = MathMaxI( iVisible-WindowBarsPerChart(),0);// Shft
static bool drawOnTop = false;
if      (Bid >= topQuarter) drawOnTop = false;  // Hysteresis - previous
else if (Bid <= botQuarter) drawOnTop = true;   // location otherwise.
if (drawOnTop)  bottom  = topQuarter;
else            top     = botQuarter;
for(iWpr = MathMinI(iWprBegin, iVisible); iWpr >= iVisEnd; iWpr--)
    Polyline( WPR_NAME, wprValue[iWpr], Color.Wpr, iWpr,
              0., 100., bottom, top );
Rétrocompatible :
void TLine( string name, datetime T0, double P0, datetime T1, double P1,
            color clr, double V0=INF, double V1=INF, bool ray=false){
    if (!Show.Objects)  return;                         #define WINDOW_MAIN 0
    if      (ObjectMove( name, 0, T0, P0 ))     ObjectMove(name, 1, T1, P1);
    else if (!ObjectCreate( name, OBJ_TREND, WINDOW_MAIN, T0, P0, T1, P1 ))
        Alert("ObjectCreate(",name,",TREND) failed: ", GetLastError() );
    else if (!ObjectSet( name, OBJPROP_RAY, ray ))
        Alert("ObjectSet(", name, ",Ray) failed: ", GetLastError());
    if (!ObjectSet(name, OBJPROP_COLOR, clr )) // Allow color change
        Alert("ObjectSet(", name, ",Color) [2] failed: ", GetLastError());
    if (V0 == INF || V0 == P0){
        string  P0t = PriceToStr(P0);           if (MathAbs(P0 - P1) >= Point)
                P0t = StringConcatenate(P0t, " to ", PriceToStr(P1));       }
    else if (V0 == V1)  P0t = StringConcatenate(V0,""); // Suppress trailing to
    else                P0t = StringConcatenate(V0, " to ", V1);
    if (!ObjectSetText(name, P0t, 10))
        Alert("ObjectSetText(",name,") [2] failed: ", GetLastError());
}
 
//+------------------------------------------------------------------+
//| EA equivalent of indicator buffers                               |
//+------------------------------------------------------------------+
/*  Example 1:
 *  if (...) Ordermodify(...);
 *  Polyline("SL"+(oo.ticket%99), oo.SL, Color.SL, 0);
 *
 *  Example 2:
 *  double  ELineCurr = iMA(NULL,0, ELine.Period, 0, MODE_EMA, PRICE_CLOSE, 1);
 *  string pln=Polyline("ELine", ELineCurr, Color.ELine, 1);
 *      ObjectSet(pln, OBJPROP_STYLE, STYLE_DOT);
 *      ObjectSetText(pln, "ELine="+DoubleToStr(ELineCurr,Digits), 10);
 ******************************************************************************/
#define POLYLINE_MAX 30 // Must match valueXX[]
string  lineName[POLYLINE_MAX]; // Common to Polyline/PolylineDelete and helper.
string  Polyline(string name, double value, color clr, int shift=0,
    double indiMin=INF, double indiMax=INF, double chrtMin=INF, double chrtMax=INF){
    if (!Show.Objects)  return("");         // Return the actual object name for
    static int           LRU[POLYLINE_MAX]; // further modifications, E.G. style
    for (int iLine=0; iLine < POLYLINE_MAX; iLine++){
        bool isNew = lineName[iLine] != name;   if (!isNew) break;  }
    if (isNew){
        for (iLine=0; iLine < POLYLINE_MAX; iLine++)  LRU[iLine]++;
        iLine=ArrayMaximum(LRU);  lineName[iLine]=name;
    }
    LRU[iLine] = 0;
    double  value00[], value01[], value02[], value03[], value04[],
            value05[], value06[], value07[], value08[], value09[],
            value10[], value11[], value12[], value13[], value14[],
            value15[], value16[], value17[], value18[], value19[],
            value20[], value21[], value22[], value23[], value24[],
            value25[], value26[], value27[], value28[], value29[];
    switch (iLine){
    case  0: return(PLHelper(value00, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  1: return(PLHelper(value01, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  2: return(PLHelper(value02, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  3: return(PLHelper(value03, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  4: return(PLHelper(value04, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  5: return(PLHelper(value05, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  6: return(PLHelper(value06, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  7: return(PLHelper(value07, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  8: return(PLHelper(value08, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case  9: return(PLHelper(value09, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 10: return(PLHelper(value10, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 11: return(PLHelper(value11, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 12: return(PLHelper(value12, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 13: return(PLHelper(value13, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 14: return(PLHelper(value14, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 15: return(PLHelper(value15, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 16: return(PLHelper(value16, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 17: return(PLHelper(value17, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 18: return(PLHelper(value18, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 19: return(PLHelper(value19, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 20: return(PLHelper(value20, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 21: return(PLHelper(value21, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 22: return(PLHelper(value22, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 23: return(PLHelper(value23, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 24: return(PLHelper(value24, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 25: return(PLHelper(value25, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 26: return(PLHelper(value26, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 27: return(PLHelper(value27, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 28: return(PLHelper(value28, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    case 29: return(PLHelper(value29, value, clr, iLine, isNew, shift,
                                        indiMin, indiMax, chrtMin, chrtMax));
    }
    /*NOTREACHED*/
}   // Polyline
string  PLHelper( double& mem[],    double value0,  color clr,      int iLine,
                  bool isNew,       int shift,      double indiMin,
                  double indiMax,   double chrtMin, double chrtMax ){
    string name = lineName[iLine];
    double  price0  = value0;                               if (indiMin < INF){
        if (chrtMin == INF) chrtMin = WindowPriceMin();
        if (chrtMax == INF) chrtMax = WindowPriceMax();
            price0  = (value0 - indiMin) / (indiMax - indiMin)
                    * (chrtMax - chrtMin) + chrtMin;                        }
    datetime    t0  = Time[shift];  static datetime timeL[POLYLINE_MAX];
    if (!isNew){
        if (timeL[iLine] < Time[shift+1]){      // Missing bar(s), leave a gap.
            isNew = true;                                                   }
        else if (Time[shift] < timeL[iLine]){   // Redrawing earlier bars.
            isNew = true;
            for(int iObj=ObjectsTotal()-1; iObj >= 0; iObj--){
                string on = ObjectName(iObj);
                if (StringFind(on, name) == 0)  ObjectDelete(on);
    }   }   }
    if (isNew){
        if (!ResizeBuffer(mem, 2))  return("");
        mem[1]        = price0;     static datetime timeF[POLYLINE_MAX];
        timeF[iLine]  = t0;         static color    clrLn[POLYLINE_MAX];
        clrLn[iLine]  = clr;        static int      segNo[POLYLINE_MAX];
        segNo[iLine]++;                                                     }
    else if (clrLn[iLine] != clr){  ArrayResize(mem, 2);    // Series==true;
        mem[1]        = mem[0];
        timeF[iLine]  = timeL[iLine];
        clrLn[iLine]  = clr;
        segNo[iLine]++;                                                     }
    else if (timeL[iLine] < t0){                    // New bar, remember point
        if (!ResizeBuffer(mem, ArraySize(mem)+1))               return(""); }
    mem[0]          = price0;   timeL[iLine]    = t0;
    int     iFirst  = ArraySize(mem)-1;
    double  priceF  = mem[iFirst],
            valueF  = priceF;                               if (indiMin < INF){
            valueF  = (priceF - chrtMin) / (chrtMax - chrtMin)
                    * (indiMax - indiMin) + indiMin;                        }
    datetime Tf = timeF[iLine];                                 // One bar wide
    if (t0 == Tf)   Tf += IfI(-1, +1, shift==0)*60*Period();    // to be visual
    string  objName = name+"_"+RJust(segNo[iLine],3);
    TLine(objName, Tf, priceF, t0, price0, clr, valueF, value0);
    double maxError=0;  for (int iMem=1; iMem < iFirst; iMem++){
        double  hight   = ObjectGetValueByShift(objName, iMem+shift),
                error   = MathAbs(hight - mem[iMem]);
        if (error > maxError){  maxError = error;   int iMaxError = iMem; }
    }
    if (maxError >= pips2dbl){  // Split the line into two segments at max.
        double  priceM  = mem[iMaxError],
                valueM  = priceM;                           if (indiMin < INF){
                valueM  = (priceM - chrtMin) / (chrtMax - chrtMin)
                        * (indiMax - indiMin) + indiMin;    }
        TLine(objName,  timeF[iLine],           priceF,
                        Time[iMaxError+shift],  priceM, clr, valueF, valueM);
        ArrayResize(mem, iMaxError+1);          // Drop iFirst..(iMaxError+1)
        timeF[iLine] = Time[iMaxError+shift];
        segNo[iLine]++; objName=name+"_"+RJust(segNo[iLine], 3);
        TLine(objName, timeF[iLine], priceM, t0, price0, clr, valueM, value0);
    }   // Split the line into two segments at the max.
    return(objName);
}   // PLHelper
 
WHRoeder:
J'ai modifié le code de la polyligne pour permettre les superpositions, ...
TLne Backwards compatible :
J'ai modifié le code de Polyline pour permettre les superpositions, et j'ai modifié le code de Polyline pour permettre les superpositions.
void TLine(string name, datetime T0, double P0, datetime T1, double P1,
           color clr, double V0=INF, double V1=INF, bool ray=false, int iWin=0){    
    if (!Show.Objects)  return;                         #define WINDOW_MAIN 0
    if      (ObjectMove( name, 0, T0, P0 ))     ObjectMove(name, 1, T1, P1);
    else if (!ObjectCreate( name, OBJ_TREND, iWin, T0, P0, T1, P1 ))
        Alert("ObjectCreate(",name,",TREND) failed: ", GetLastError() );
    else if (!ObjectSet( name, OBJPROP_RAY, ray ))
        Alert("ObjectSet(", name, ",Ray) failed: ", GetLastError());
    if (!ObjectSet(name, OBJPROP_COLOR, clr )) // Allow color change
        Alert("ObjectSet(", name, ",Color) [4] failed: ", GetLastError());
    if (V0 != INF)  // V0, V1 is used for non-price indicator overlayed on chart
        if (MathAbs( (V0 - V1) / MathMax(V0, V1) ) < 0.001)             string
                P0t = StringConcatenate(V0,"");
        else    P0t = StringConcatenate(V0, " to ", V1);
    else if (iWin != WINDOW_MAIN)
        if (MathAbs( (P0 - P1) / MathMax(P0, P1) ) < 0.001)
                P0t = StringConcatenate(P0,"");
        else    P0t = StringConcatenate(P0, " to ", P1);
    else if (MathAbs(P0 - P1) < Point_2)
                P0t = PriceToStr(P0);
    else        P0t = StringConcatenate(PriceToStr(P0), " to ", PriceToStr(P1));
    if (!ObjectSetText(name, P0t, 10))
        Alert("ObjectSetText(",name,") [1] failed: ", GetLastError());
}
Pour dessiner sur le sous graphique, il suffit d'utiliser iWin = WindowFind("indicatorName") ;
 
WHRoeder:
A partir d'un post sur le dessin d'indicateur sur le graphique principal et le graphique secondaire, TLine pourrait être utilisé pour les deux avec des modifications.
Pour dessiner sur le sous graphique, il suffit d'utiliser iWin = WindowFind("indicatorName") ;

Merci
 

Heure de fermeture du marché.

Je voulais fermer tous les ordres avant la fin de la semaine (clôture du marché le vendredi) afin d'éviter les pertes si le marché s'effondre à la fin de la semaine, en passant le SL. (Ceci n'est pas modélisé dans le testeur).

La question est donc de savoir quand le marché ferme (ou ouvre). Toutes les publications et recherches sur le net sont tout simplement fausses. De Forex Education - Introduction au Forex - IBFX Le marché du Forex fonctionne 24 heures par jour, 5,5 jours par semaine (de 18h00 ET le dimanche à 16h00 ET le vendredi) C'est ET - heure locale de New York.

Cela signifie que tous les affichages dépendent de la date à laquelle ils ont été effectués, car la limite de l'heure légale varie d'une année à l'autre.

Cela signifie qu'il est nécessaire de calculer quand l'heure légale de NY commence et se termine, pour la barre en question. (Le problème est que Windows ne fournit pas de routines de conversion, sauf entre la TZ actuelle et l'UTC, et seulement pour l'année en cours. Si le PC n'est pas sur ET, cela ne peut pas être fait directement. De plus, jusqu'à la sortie de Windows8, vous ne pouvez pas obtenir de conversions pour ET et les années précédentes. Et en regardant le registre de Win7, les valeurs ne couvrent que l'année 2005 (et elles étaient erronées si je les ai bien lues.) Je ne parie donc pas que Win8 sera meilleur.

Cela signifie qu'il est nécessaire de calculer moi-même l'heure d'été. J'ai mis à jour mon code: TimeGmt() et LocalTimeGMT() avec des arguments par défaut, un peu de documentation supplémentaire, et des vérifications, et j'ai écrit du code pour calculer l'heure de fermeture du marché. Bonne lecture.

#define HR2400          86400                   // 24 * 3600
datetime TimeOfDay(datetime when){  return( when % HR2400          );       }
datetime DateOfDay(datetime when){  return( when - TimeOfDay(when) );       }
datetime    now.srv,    now.utc,    mkt.closes.srv;
:
    now.srv = TimeCurrent();
    now.utc = TimeGMT(now.srv);                 // May update Srvr.To.UTC.Hours
    if (now.srv > mkt.closes.srv){              // Compute next market close
        // Market closes Friday 4PM ET (NY local time) and opens Sunday 6PM ET.
        // That's either 2100z or 2000z depending on DST.
        // 18:00 Friday   in America/New_York
        // 12:00 Friday   in Pacific/Honolulu
        // 08:00 Saturday in Australia/Melbourne
        // 07:00 Saturday in Asia/Tokyo
        #define DOW_FRIDAY  5
        #define HR2100      75600   // 21 * 3600
        #define NY_TZ      -18000   // -5 * 3600 UTC-5 (STD) or UTC-4 (DST)
        datetime mktClosesUTC   = DateOfDay(now.utc)
                                + HR2400*(DOW_FRIDAY - TimeDayOfWeek(now.utc))
                                + HR2100;
        if (IsNYonDST(mktClosesUTC + NY_TZ))    mktClosesUTC -= 3600;   // UTC-4
        mkt.closes.srv = TimeServer(mktClosesUTC);
    }                                           // Compute next market close
:
//+------------------------------------------------------------------+
//| GMT Time                                                         |
//+------------------------------------------------------------------+
datetime TimeGMT(datetime serverTime=0){            // Server time to GMT time.
    if (serverTime == 0)    serverTime = TimeCurrent();
    static datetime nextAutoUpdate;     if (serverTime >= nextAutoUpdate){
        nextAutoUpdate = serverTime + 7200;
        if (Srvr.To.UTC.Auto
        )if(IsDllsAllowed()){                               // Complained @ init
            int     srvrToUTC       = LocalTimeGMT() - TimeCurrent();
            double  nearestHalfHour = MathRound(srvrToUTC / 1800.);
            Srvr.To.UTC.Hours       = nearestHalfHour / 2.; // Update external
    }   }
    return (serverTime + Srvr.To.UTC.Hours*3600.);
}
datetime TimeServer(datetime gmtTime){              // Server time to GMT time.
    return (gmtTime - Srvr.To.UTC.Hours*3600.);
}
#import "kernel32.dll"
int  GetTimeZoneInformation(int& TZInfoArray[]);
#import
datetime LocalTimeGMT(){    // TimeLocal to GMT forum.mql4.com/12057#522900
    // This is called only by TimeGMT. Check for IsDLLsAllowed() done there.
    int TZInfoArray[43];
    int tz  = GetTimeZoneInformation(TZInfoArray);
    int GMTshift    = TZInfoArray[0];   // GetTimeZoneInformation will return
    #define TIME_ZONE_ID_DAYLIGHT 2     // the right Bias even when it returns
    #define TIME_ZONE_ID_UNKNOWN  0     // UNKNOWN
    if (tz == TIME_ZONE_ID_DAYLIGHT || tz == TIME_ZONE_ID_UNKNOWN)
        GMTshift += TZInfoArray[42];
    return (TimeLocal() + GMTshift*60);
/*
 *  msdn.microsoft.com/en-us/library/windows/desktop/ms724421%28v=vs.85%29.aspx
 *  typedef struct _TIME_ZONE_INFORMATION {     typedef struct _SYSTEMTIME {
 *  LONG       Bias;              [ 0]  (min)   WORD wYear;         [0]
 *  WCHAR      StandardName[32];  [ 1]          WORD wMonth;            Jan=1
 *  SYSTEMTIME StandardDate;      [17]          WORD wDayOfWeek;    [1] Sun=1
 *  LONG       StandardBias;      [21]          WORD wDay;
 *  WCHAR      DaylightName[32];  [22]          WORD wHour;         [2]
 *  SYSTEMTIME DaylightDate;      [38]          WORD wMinute;
 *  LONG       DaylightBias;      [42]          WORD wSecond;       [3]
 *                                    }         WORD wMilliseconds;        }
 */
}
bool IsNYonDST(datetime whenNY){
    // Market opens Sunday 6PM ET (NY local time) and closes Friday 4PM ET.
    // DST changes at 2AM Sunday, when the market is closed. I don't have to
    // worry about the passed time here, only the date.
    int year    = TimeYear(     whenNY);                   #define MARCH     3
    int mon     = TimeMonth(    whenNY);                   #define APRIL     4
    int dom     = TimeDay(      whenNY);                   #define OCTOBER  10
    int dow     = TimeDayOfWeek(whenNY);                   #define NOVEMBER 11
    // http://en.wikipedia.org/wiki/Daylight_saving_time_in_the_United_States
    //                                      #History_of_DST_in_the_United_States
    // 1986-2006    DST the first Sunday in April to the last Sunday in October
    // 2007 on              second Sunday March         first Sunday in November
    if (year < 2007){ int   monBeg=APRIL,   secndSun=0,  monEnd=OCTOBER;    }
    else{                   monBeg=MARCH;   secndSun=7;  monEnd=NOVEMBER;   }
    if (mon < monBeg                     )  return(false);  // Early spring.
    if (                     mon > monEnd)  return(false);  // Late fall.
    if (mon != monBeg){ if (mon != monEnd)  return(true);   // Summer.
        if (year < 2007){   // Find last Sun = dom - (dow-SUNDAY) but SUNDAY==0
            for (int lastSun = dom-dow; lastSun+7 <= 31; lastSun += 7){}
            return (dom < lastSun);                         // DST Before Sun. &
    }   }                                                   // not on markt open
    // Otherwise first or second Sunday of MonBegin or first Sunday of MonEnd
    for (int firstSun = dom + 7-dow; firstSun > 7; firstSun--){}
    if (mon == monBeg)  return (firstSun+secndSun <= dom);  // DST On/After
    return (dom < firstSun);                                // DST Before Sun.
}
 
WHRoeder: correction.
    // Otherwise first or second Sunday of MonBegin or first Sunday of MonEnd
//  for (int firstSun = dom + 7-dow; firstSun > 7; firstSun--){}
    for (int firstSun = dom + 7-dow; firstSun > 7; firstSun -= 7){}
 

Ce sont de bons points, il y a beaucoup plus de choses qui sont une conjecture même avec les fonctions MT4, qui ne retournent pas toujours la valeur correcte. Par exemple, les informations sur le courtier et le serveur et les paramètres de négociation, comme le spread variable, l'ECN ou non, le SL requis ou non, ne sont fournies que par la gestion des erreurs, les informations sur les symboles, etc.

Beaucoup d'entre eux sont simplement des choses de base qui ne peuvent (et ne devraient) pas être facilement vérifiées. Par exemple, les informations sur les graphiques ouverts et les données historiques, les informations sur l'heure (GMT, fuseau horaire, DST), les informations sur l'ouverture et la fermeture du marché.

Une reprise après sinistre serait vraiment bien, à commencer par le fait que MT4 ne s'arrête pas et ne redémarre pas comme il le souhaite (mise à jour), ainsi que l'arrêt correct de terminal.exe, qui reste figé dans le gestionnaire de tâches même plusieurs heures après la fermeture du terminal (et qui était censé être fermé correctement avec le bouton de fermeture sans aucun message d'erreur).

Une sorte de support de centre de données local serait également bien, cela rendrait le travail plus facile au lieu de variables globales limitées et de fichiers ouverts. Sans parler du stockage des données ask, bid, (spread) tick qui est manquant.

Il y a beaucoup de choses manquantes simples qui rendent la vie beaucoup plus difficile ensemble, et c'est une quantité terrible de travail pour les gérer correctement si possible. De nombreux conseils et astuces externes, voire des hacks, sont nécessaires pour un fonctionnement correct et étendu. Je ne blâme personne qui publie une stratégie sur la base de code et ne gère pas tous les problèmes possibles (dont beaucoup sont spécifiques à un courtier) avec MT4 ou le serveur - surtout quand le point est sur la stratégie et non sur la gestion des erreurs.

Même des choses très simples manquent, nous ne pouvons pas gérer les fichiers journaux qui peuvent facilement atteindre des centaines de mégaoctets ou plus lorsque quelque chose va vraiment mal. Ils grossissent jusqu'à ce que le disque soit plein et rien ne peut être fait, pas même une option dans les paramètres du terminal sur la gestion des fichiers journaux.

Raison: