Neden Kod Tabanında Tam EA YOKTUR? - sayfa 3

 
WHRoeder :
İşte benim eksi gerçek ticaret mantığı.
İşlem saati/gün filtresiyle ilgili bir PM aldım. Talep Pazartesi-Cuma 1800-0600 idi. Bu, Pazartesi günü 0-0600 ve Cuma günü 1800-kapanışı hariç tutmayı gerektirir. Kod, zaman aşımına izin verdi, ancak günlerce izin vermedi. Artırma:
     /*++++ 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*/ }
Ve RaptorUK'un yorumu için yaptığım düzeltme:
 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 :
Ve RaptorUK'un yorumu için yaptığım düzeltme:
aCurrencyChange = aPriceChange * OrderSize() * DeltaValuePerLot() olduğundan PointValuePerLot'u DeltaValuePerLot olarak yeniden adlandırdım. Ayrıca daha fazla yorum ekledi.
 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); }
 
Çoklu Çizgi kodunu bindirmelere izin verecek şekilde değiştirdim, örneğin:
 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 );
Geriye dönük uyumlu:
 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 :
Çoklu çizgi kodunu bindirmelere izin verecek şekilde değiştirdim, ..
TLne Geriye dönük uyumlu:
Hem ana çizelgede hem de alt çizelgede gösterge çizimiyle ilgili bir gönderiden, TLine değişikliklerle her ikisi için de kullanılabilir.
 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 ());
}
Alt çizelge üzerinde çizim yapmak için sadece iWin = WindowFind("indicatorName"); işlevini kullanın.
 
WHRoeder :
Hem ana çizelgede hem de alt çizelgede gösterge çizimiyle ilgili bir gönderiden, TLine değişikliklerle her ikisi için de kullanılabilir.
Alt çizelge üzerinde çizim yapmak için sadece iWin = WindowFind("indicatorName"); işlevini kullanın.

teşekkürler
 

Piyasa kapanış zamanı.

SL'yi geçerek hafta sonundaki pazar boşluğunun zarar görmesini önlemek için tüm siparişleri hafta sonundan önce kapatmak istedim (piyasa Cuma günü kapanır). (Bu, test cihazında modellenmemiştir.)

Yani soru şu ki, piyasa ne zaman kapanıyor (veya açılıyor)? İnternetteki tüm ilanlar ve aramalar tamamen yanlış. Forex Eğitiminden - Forex'e Giriş - IBFX Forex piyasası haftanın 5.5 günü, günde 24 saat çalışır (Pazar günü 18:00 ET'den Cuma 16:00 ET'ye kadar) Bu, ET - New York yerel saatidir.

Bu, DST sınırları yıldan yıla değiştiğinden, Tüm kayıtların ne zaman yapıldığına bağlı olduğu anlamına gelir.

Bu, söz konusu çubuk için NY DST'nin ne zaman başlayıp bittiğini hesaplamanın gerekli olduğu anlamına gelir. (Geriye dönük testler için en azından 2000 değerlerine ihtiyacımız var.) Sorun şu ki, Windows mevcut TZ ve UTC arasında ve yalnızca mevcut yıl için dönüştürme rutinleri sağlamaz. PC ET'de değilse, doğrudan yapılamaz. Dahası, Windows8 çıkana kadar ET ve önceki yıllar için dönüşüm alamazsınız. Ve Win7'deki Kayıt Defterine baktığımda, değerler sadece 2005'i kapsıyor (ve eğer doğru okursam bunlar yanlıştı.) Yani Win8'in daha iyi olacağına bahse girmiyorum.

Bu, DST'yi kendim hesaplamam gerektiği anlamına gelir. Kodumu güncelledim: TimeGmt() ve LocalTimeGMT() varsayılan argümanlar, bazı ek belgeler ve kontrollerle ve piyasa kapanış zamanını hesaplamak için kod yazdım. Zevk almak.

 #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 : düzeltme.
     // 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 ){}
 

Bunlar iyi noktalar, MT4 işlevlerinde bile her zaman doğru değeri döndürmeyen tahmin niteliğinde olan daha birçok şey var. Örneğin, komisyoncu ve sunucu bilgileri ve değişken spread, ECN veya değil, SL gerekli veya değil gibi ticaret parametreleri, yalnızca hata işleme, sembol bilgileri vb.

Bunların çoğu, kolayca kontrol edilemeyen (ve kontrol edilmesi gereken) basit temel şeylerdir. Örneğin, açık grafikler ve geçmiş verileri hakkında bilgi, zaman bilgisi (GMT, saat dilimi, DST gibi), piyasa açılışı, kapanış bilgisi.

Olağanüstü Durum Kurtarma gerçekten iyi olurdu, MT4'ün istediği gibi kapanmaması ve yeniden başlatılması (güncelleme), ayrıca terminalin kapanmasından saatler sonra bile görev yöneticisinde donmuş kalan terminal.exe düzgün kapanması (ve kapalı olduğu düşünülüyor) herhangi bir hata mesajı olmadan kapat düğmesiyle düzgün şekilde).

Bir tür yerel veri merkezi desteği de iyi olurdu, sınırlı global değişkenler ve açılan dosyalar yerine çalışmayı kolaylaştırırdı. Eksik olan talep, teklif, (yayılma) onay verilerinin depolanmasından bahsetmiyorum bile.

Birlikte hayatı daha da zorlaştıran birçok basit eksik şey var ve mümkünse bunları doğru bir şekilde halletmek için korkunç miktarda iştir. Kapsamlı düzgün çalışma için birçok harici ipucu ve püf noktası, hatta hack'ler gereklidir. Kod tabanında bir strateji yayınlayan ve MT4 veya sunucuyla ilgili tüm olası (çoğu aracıya özgü) sorunları çözmeyen hiç kimseyi suçlamıyorum - özellikle de nokta hata işlemede değil stratejideyse.

Çok basit şeyler bile eksiktir, bir şeyler gerçekten ters gittiğinde kolayca yüzlerce megabayt veya daha fazla büyüyebilen günlük dosyalarıyla ilgilenemiyoruz. Disk dolana kadar büyürler ve hiçbir şey yapılamaz, hatta günlük dosyası işlemede terminal ayarlarında bir seçenek bile yoktur.