Author: Maxim Kuznetsov
Price Data Components
Series array that contains open time of each bar
Orders Execution
It can change open orders parameters, due to possible stepping strategyIt Closes Orders by itself It automatically opens orders when conditions are reached
Indicators Used
Moving average indicator
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Massaracsh
ÿþ//+------------------------------------------------------------------+

//|                                                   Massaracsh.mq4 |

//|                                                  Maxim Kuznetsov |

//|                                          https://www.luxtrade.tk |

//+------------------------------------------------------------------+

#property copyright "Maxim Kuznetsov"

#property link      "https://www.luxtrade.tk"

#property version   "1.00"

#property strict



// <0AA0@0:H, >=-65 0=B8-3@5<;8=

// "=8:>340,=8:>340 =5 :>@<8B5 8E ?>A;5 ?>;C=>G8!" (c)

// A>2A5<  ,+ A>25B=8:,

// 2 =Q< OrdersTotal() 8 F8:;>2 for/while "# ) :-)

// >= 4065 =5 AB@5<8BAO ?>;CG0BL ?@81K;L

// ------------------------------

// 2A5 CA8;8O B>;L:> GB>1K ;8H8BL ?@81K;8 DC, 

// =5 ?@>A:>;L78BL, =5 40BL A2>?, >B18BL A?@54

// 0 ?@>G55 2 A>25B=8:0E 2>>1I5 <0;> 206=> :-)

//

// ?@8 ?@>872>;L=> 2K1@0==>< A83=0;5 - 1C45B 3>@87>=B0;L=0O ;8=8O

// (?>:0 GCBL ?>420;5==0O 2=87, 2848<> >B >:@C3;5=89)

// A "A>?;O<8" <0@B8=359;0 >B1820NI8< @0AE>4K

//

// A83=0; 2E>40 - ;N1>9 (2 40==>< A;CG05 ?5@5A5G5=85 <0H5:)

// >B:@KB85 ?> @K=:C

// "59: 8 !B>? D8:A8@>20==K5 2 ?C=:B0E

// 70:@KB85 B>;L:> ?> AB>? 8;8 B59:

// 4> 70:@KB8O B5:CI59 A45;:8, =>2K5 =5 >B:@K20NBAO

//

// === MM, B>;L:> 4;O >B182:8 A?@540  ==

// ?@8 ?@>83@KH5, C25;8G8205< "59: 8 !B>? =0 1 A?@54.

// ?@8 2K83@KH5 45;05< >1@0B=K9 H03 ?>:0 =5 25@=Q<AO 2 ?@56=89 480?07>=.

//

// 5A;8 2 EC4HCN AB>@>=C A45;0=> 1>;LH5 STEPS H03>2

// 2:;NG05BAO <0@B8=359; =0 2>72@0B A?@540 (8 ?@>G8E @0AE>4>2)

//

// ?@8 C25;8G5=88 10;0=A0 MM @5AB0@BC5B (2A5 4>;38 ?@>I0NBAO, <0@B8= >B<5=O5BAO)

// 5A;8 <0@B8=359; C65 2:;NG5=, B0:>9-65 @5AB0@B ?> M:28B8

// 

// 8A?>;L7C5BAO BEVEN/NOREWARD, B@0;K 4065 8 =5 ?@>1C9B5 45;0BL, A;><05B5 MM 

// -------------------------------

// =5 4;O E0;O2I8:>2, A83=0;LI8:>2 8 15745;L=8:>2,

// GB>1K 70?CAB8BL E>BO-1K =0 45<:5 ?@8;>68B5 CA8;8O

// @50;87C9B5 ?>;=>ABLN DC=:F88 SaveState LoadState CheckState ClearState

// @0A?@>AB@0==5=85 :>40 A ?>;=K<8 DC=:F8O<8   "!"#"!/

// -------------------------------

// ! . 70<5G0=8O 8 8458 ?@> 40;L=59H55 ">15AA2>?;820=85" 8 "45A?@548@>20=85"

// 



// MustHave (=5 >A8;5==>5 2 40==>9 25@A88, => AB@>3> =C6=>5)

// - 70<5=0 DC=:F88 Print =0 A>1AB25==CN. 5G0BL 2 >1I89 6C@=0; - :>340 A>2A5< =5G53> 45;0BL

// - 5IQ 1>;55 1KAB@K9 OnTick - <=>3> G53> <>6=> C=5AB8 2 B09<5@/OnSecond

// - 2K@02=820=85 <5B:8 M30 ?> 2@5<5=8, GB>1K 157 ;8H=8E A5:C=4 (>=8 B0< G0AB>)

// - C40;5=85 A5@25@=KE AB>?/B59: 4> ?>;C=>G8 8 ?5@52KAB02;5=85 ?>A;5

// ToDo (?>;57=>5, ?>=OB=>5, =5 ?5@2>>G5@54=>5)

// - @50;L=K5 AB>?/B59: =0 A5@25@5 - =0 50-100 ?C=:B>2 40;LH5 28@BC0;L=KE, B>;L:> =0 A;CG09 020@89 8 A1>52.

// - @07@5H5=8O buy/sell >B ?>;>68B5;L=KE/>B@8F0B5;L=KE A2>?>2. 

// - C40;5=85 =5C40G=KE >@45@>2 ?@8 >B@8F0B5;L=>< A2>?5 4> ?>;=>G8 8 ?5@52KAB2;5=85 2 0780BA:CN A5AA8N

// - B>G=K5 70<5@K 2@5<5=8 8 7045@65: <564C A>25B=8:>< 8 A5@25@><

// - 83=>@8@>20=85 "?@>A@>G5==KE" B8:>2 =0 >A=>25 70<5@>2

// - 5IQ 1>;55 B>G=K9 CGQB ?@8 <0@B8=359;5. @8=8<0BL 2 @0AAGQB "E2>AB" >:@C3;5=89.

// - <8:@>>?B8<870F88 - 2AQ GB> <>6=> @0AAG8BK20BL 8 70?@0H820BL A45;0BL 70@0=55

// - 45B5:F8O =>2>ABKE 2A?;5A:>2 - =5B8G=0O G0AB>B0 B8:>2, =5C@>G=>5 @0AH8@5=85 A?@540, B8:8 2 >4=C AB>@>=C. 8 :0: =0 MB> @5038@>20BL

// - ;>28BL 87<5=5=8O StopLevel, Leverage, MinLot 8 GB> ?@8 MB>< 45;0BL

// Tune (=5 ?><5H05B, :><C A8;L=> =04>, <>65B 8 A0< 4>1028BL)

// - 10;0=A>2K5 >?5@0F88. > E>@>H5<C 45;0NBAO ?@8 >B:;NG5==KE A>25B=8:0E, => >1KG=> 1K205B ?> ?;>E><C

// - 48=0<8G5A:89 ;>B, C25;8G5=85 >1JQ<0 A @>AB>< 45?>78B0.%>BO : G5<C MB> ?

// - 040?B0F8O : :@8?B0< - 1>;LH>5 G8A;> 7=0:>2 2 8AG8A;5=88 45=53 8 >1JQ<>2, ?5@5<5==>5 7=0G5=85 _Point

// 



input double   LOTS=0.05;        // =0G0;L=K9 ;>B

input int      SL=80;        // AB>?-;>AA, ?C=:B>2 >B >B:@KB8O

input int      TP=100;         // B59:-?@>D8B, ?C=:B>2 >B >B:@KB8O

input int      SPREAD=20;      // CGQB=K9 A?@54, >=-65 <0:A8<0;L=K9 B>@3>2K9

input int      STEPS=10;      // H03>2 C25;8G5=8O SL/TP, 40;LH5 <0@B8=

input int      START_STEP=5; // =0G0;L=K9 H03 C25;8G5=8O

input int      HOLD_HOURS=2; // G5@57 A:>;L:> G0A>2 A>:@0I0BL 480?07>=

                              // GB>1K =5 ?5@5A86820BL



// 8 2 ?>;=>GL - =8:0:8E 459AB289, 4065 A83=0;K 83=>@8BL

// /  , =04> 4065 C18@0BL SL/TP 8 2A5 >B;>6:8, GB>1K =5 A=5A;> ?;OA:>9 A?@540. >A;5 ?>;C=>G8 ?5@52KAB028BL. -B> E;51 DC, 0 >=8 8 B0: B>;ABK5

// C1KB>G=K5 >@45@0 B>65 <>6=> 70@0=55 70:@KBL, GB>1K =5 =0<0BK20BL A2>?.  =0G0;5 0788 ?>GB8 2A5340 8E <>6=> ?5@5>B:@KBL =0 ?0@C A?@54>2 ;CGH5

input int      MINUTES_BEFORE_MIDNIGHT=20; // 70 A:>;L:> <8=CB 4> ?>;C=>G8

input int      MINUTES_AFTER_MIDNIGHT=100; // 8 A:>;L:> ?>A;5,  " ",



// B>@3>2K9 A83=0;, 4;O B5AB0, ;8HL 1K 1K; ;-)

// ?5@5A5G5=8O -H:5 ?>GB8 @02=>7=0G=>5 random()

// ---------------------------------------------

// ;O 99.9% "8=48:0B>@=KE" A>25B=8:>2 01A>;NB=> ?>D8:

// >B:@KBLAO A@07C =0 10@5 8;8 2 B5G5=88 =51>;LH>3> 2@5<5=8. "0:-65 A 70:@KB85<.

// 

// 48=AB25==K9 ?@O<>9 C1KB>: - !  8 ?@>A:0;L7K20=8O.

// 8E =04> <8=8<878@>20BL A> AB@0H=>9 A8;>9.

// B>@3>20BL B>;L:> ?@8 <8=8<0;L=>< A?@545, A@07C-2;QB ?> ?>ABC?;5=8N B8:0

// 8 =8:>340 =5 =0 3@0=8F0E M30 (A;8H:>< <=>3> A>1KB89, B0< B>G=> EC4H89 20@80=B, A:>;L65=8O 8 @5:2>BK)

//



input ENUM_TIMEFRAMES TIMEFRAME=PERIOD_CURRENT;



input int      FAST_MA_METHOD=MODE_LWMA;

input int      FAST_MA_PERIOD=13;

input int      FAST_MA_SHIFT=1;

input ENUM_APPLIED_PRICE  FAST_MA_PRICE=PRICE_CLOSE;



input int      SLOW_MA_METHOD=MODE_SMA;

input int      SLOW_MA_PERIOD=30;

input int      SLOW_MA_SHIFT=1;

input ENUM_APPLIED_PRICE  SLOW_MA_PRICE=PRICE_CLOSE;



input bool     INVERSE=false;

// ?@>G85 ?0@0<5B@K

sinput int MAGIC=3321;



// ?@>G88 =0AB@>9:8

const int TIMER_SECONDS=1;       // G0AB>B0 B09<5@0. 

const int BUYSELL_TIMEOUT=13*60; // B90<0CB 4;O Buy/Sell

const int SEC_BEFORE_M30=7;      // 70?@5B B>@3>2;8 4> 3@0=8FK M30

const int SEC_AFTER_M30=13;      // @07@5H5=85 B>@3>2;8 ?>A;5 M30



#include <stdlib.mqh>



//  " +   &/ "  !

// GB>1K ?><5=OBL A83=0;, ?5@545;09B5 DC=:F88 CheckParameters, GetSignal 



// ?@>25@:0 ?0@0<5B@>2 =0 :>@@5:B=>ABL

bool CheckParameters()

{

   // ok

   return true;

}

// ?>;CG8BL A83=0; =0 >B:@KB88 (70:@KB88) 10@0

int GetSignal()

{

   double data_fast[4];

   double data_slow[4];

   for(int i=0;i<4;i++) {

      data_fast[i]=iMA(_Symbol,TIMEFRAME,FAST_MA_PERIOD,0,FAST_MA_METHOD,FAST_MA_PRICE,i+FAST_MA_SHIFT);

      if (!MathIsValidNumber(data_fast[i]) || data_fast[i]==EMPTY_VALUE || data_fast[i]==0) return false;

      data_slow[i]=iMA(_Symbol,TIMEFRAME,SLOW_MA_PERIOD,0,SLOW_MA_METHOD,SLOW_MA_PRICE,i+SLOW_MA_SHIFT);

      if (!MathIsValidNumber(data_slow[i]) || data_slow[i]==EMPTY_VALUE || data_slow[i]==0) return false;

   }

   int signal=-1; // =5B A83=0;>2

   if (CrossedUp(data_fast,data_slow,3)) {

      if (!INVERSE)

         signal=OP_BUY;

      else

         signal=OP_SELL;

   }

   else if (CrossedDn(data_fast,data_slow,3)) {

      if (!INVERSE)

         signal=OP_SELL;

      else

         signal=OP_BUY;

   } 

   

   return signal;

}

bool CrossedUp(double &fast[],double &slow[],int shift)

{

   if (fast[shift]>slow[shift] && fast[shift-1]<=slow[shift-1]) return true;

   return false;

}

bool CrossedDn(double &fast[],double &slow[],int shift)

{

   if (fast[shift]<slow[shift] && fast[shift-1]>=slow[shift-1]) return true;

   return false;

}



///////////////////////

//     !"

//////////////////////



//////////////////////

// A>AB>O=85 A>25B=8:0

// :>B>@>5 =04> A>E@0=OBL/>1=>2;OBL/2>AAB0=02;820BL

//////////////////////



// >@45@

int ticket=-1;             // B8:5B >B:@KB>3> >@45@0

int step=0;                // B5:CI89 H03 =0@0I820=8O TP/SL

double virtualStopLoss;    // 5A;8 B8:5B >B:@KB - BCB 28@BC0;L=K9 SL

double virtualTakeProfit;  // 

int pointsStopLoss;        // StopLoss 8 TakeProfit 2 ?C=:B0E

int pointsTakeProfit;      // 2KAG8B0==K5 ?@8 >B:@KB88 >@45@0



// 10;0=A

double initialBalance;  // =0G0;L=K9 10;0=A

double currBalance;     // B5:CI89

double maxBalance;      // <0:A8<0;L=> 4>AB83=CBK9

double minBalance;      // <8=8<C< ?>A;5 <0:A8<C<0

double credit;          // ?>B@0G5=> 2 A2>?K/A?@54K/:><8AA8N/?@>A:0;L7K20=85



// >1@0B8B5 2=8<0=85 =0 :>;-2> D8=0=A>2KE ?>:070B5;59

// GB>1K "?>9<0BL" <><5=B :>340 ?@>B>B8? =0G8=05B ?@8=>A8BL ?@81K;L

// 0 @50;L=K9 @>1>B 2?0405B 2 C1KB:8, 8E 4>;6=> 1KBL 5IQ 1>;LH5.

// !B@>389 ?>AB0B59=K9 CGQB. !:>;L:> :C40 ?>B@0B8;>AL 8 >B:C40 G53> ?@8;5B5;>

// A@07C 2 20@80=B0E - :0: 5ABL, A 0-< A?@54><, 157 MM 8 B0: 40;55



// ?;0=8@C5<K5 459AB28O

enum ENUM_ACTION {

   ACTION_NONE,

   ACTION_BUY,

   ACTION_SELL,

   ACTION_CLOSE

};

int scheduledAction=ACTION_NONE;    // 70?;0=8@>20==>5 459AB285 ACTION_BUY ACTION_SELL ACTION_CLOSE

datetime scheduledTimeout=0;        // B09<0CB. ;O CLOSE 83=>@8@C5BAO



bool InitState()

{

   ticket=-1;

   step=0;

   virtualStopLoss=0;   

   virtualTakeProfit=0;   

   initialBalance=AccountBalance();

   currBalance=maxBalance=minBalance=initialBalance;

   credit=0;

   pointsStopLoss=0;

   pointsTakeProfit=0;

   scheduledAction=ACTION_NONE;

   scheduledTimeout=0;

   return true;

}



// 703@C7:0 A>AB>O=8O ?@8 (@5)AB0@B5 A>25B=8:0

bool LoadState()

{

   return true;

}

// ?>;=>5 A>E@0=5=85 (?@8 7025@H5=88)

bool SaveState()

{

   return true;

}

// G0AB8G=>5 A>E@0=5=85 ?@8 87<5=5=8OE

bool UpdateState()

{

   return SaveState();

}

// ?@>25@:0 :>@@5:B=>AB8 ?>A;5 703@C7:8

bool CheckState()

{

   if (AccountBalance()!=currBalance) {

      Alert("Alien deals!");

   }

   return true;

}

// >G8AB:0 A>AB>O=85 ?@8 >H81:5 (GB>1K ?> =>2>9 =5 703@C78BL)

bool ClearState()

{

   return true;

}



//////////////////////////

// @01>G85 40==K5

/////////////////////////

bool inited=false;      // ?@87=0: 725@H5=8O 8=8F80;870F88

// <5B:8 2@5<5=8

datetime serverTime=0;    // ?>A;54=55 8725AB=>5 2@5<O A5@25@0



datetime nightFromTime=0; // =0G0;> "?>;=>G8"

datetime nightToTime=0;   // :>=5F ?>;=>G8



datetime barTime=0;       // 2@5<O >B:@KB8O B5:CI53> 10@0

datetime nextBarTime=0;   // <8=.2@5<O >B:@KB8O A;54CNI53> 10@0



datetime m30Time=0;       // 2@5<O =0G0;0 B5:CI53> M30

datetime nextM30=0;       // <8=.2@5<O A;54CNI53> M30



datetime dayTime=0;       // 2@5<O =0G0;0 B5:CI53> 4=O (D1)

datetime nextDayTime=0;   // 2@5<O =0G0;0 A;54CNI53> 4=O (D1)



bool hasTimer=false;       // 2:;NG8;AO ;8 B09<5@?

datetime nextTimerLocalTime=0;   // 5A;8 B09<5@ =5 2:;NG8;AO, B> :>=B>@>;;8@>20BL B0:

// >1@0B8B5 2=8<0=85, A:>;L:> <5B>: 2@5<5=8.

// 2 "1>52KE" A>25B=8:0E 8E A8;L=> 1>;LH5 8 @07=KE, >B @07=KE B09<5@>2 (;>:0;L=K9,A5@25@,A8<2>;)

// ?5@2>5 GB> 1C45B5 45;0BL - MDD5:B82=K9 8 =5?@>6>@;82K9 ?;0=8@>2I8: 8 A;C61C 2@5<5=8 

// 0 =5 3@>74LO :;0AA>2, :0: C =0A ?@8=OB>



bool InitData()

{

   inited=false;

   serverTime=TimeCurrent();

   

   barTime=iTime(_Symbol,TIMEFRAME,0);    // FIXME: 2 @50;5 =04> 2K@02=820BL

   nextBarTime=barTime+PeriodSeconds(_Period);  

   

   m30Time=iTime(_Symbol,PERIOD_M30,0);   // B0:-65 =04> 2K@02=820BL

   nextM30=m30Time+30*60;                 

   

   MqlDateTime dt;TimeToStruct(serverTime,dt);

   dt.hour=0;

   dt.min=0;

   dt.sec=0;



   dayTime=StructToTime(dt);

   nextDayTime=dayTime+24*60*60;



   nightFromTime=nextDayTime-MINUTES_BEFORE_MIDNIGHT*60*60;

   nightToTime=dayTime+MINUTES_AFTER_MIDNIGHT*60*60;

   

   scheduledAction=ACTION_NONE;

   scheduledTimeout=0;



   hasTimer=false;

   nextTimerLocalTime=0;

   return true;   

}



int OnInit()

{

   if (!CheckParameters()) {

      return INIT_PARAMETERS_INCORRECT;

   }

   if (!InitState()) {

      return INIT_FAILED;

   }

   if (!InitData()) {

      return INIT_FAILED;

   }

   // ?@>1C5< 703@C78BL ?@56=55 A>AB>O=85

   if (LoadState()) {

      // 87 D09;0, 107K 8;8 3;>1.?5@5<5==KE 703@C78;8AL

      if (!CheckState()) {

         // ?@>25@8;8, ?;>E> 2AQ..

         ClearState(); // C40;8BL 8 ?>@C30BLAO

         Alert("#AQ ?@>?0;>, H5D !");

         return INIT_FAILED;

      }

   }

   if (!IsTesting() && !IsOptimization() && TIMER_SECONDS>0) {

      // B09<5@ <>65B 8 =5 2:;NG8BAO, MB> =04> CG8BK20BL

      hasTimer=EventSetTimer(TIMER_SECONDS);

   }

   return(INIT_SUCCEEDED);

}

// ?>AB-8=8F8;070F8O 2=CB@8 OnTick, :>340 A2O7L C65 5ABL, B8:8 ?>H;8, 2AQ ?> 8455 ?>43@C65=>

bool PostInit()

{

   return true;

}



void OnDeinit(const int reason)

{

   if (inited) {

      // 8=8F80;870F8O 1K;0 ?@>2545=0, AB59B <>3 <5=OBAO 2> 2@5<O @01>BK

      SaveState(); // A>E@0=O5< :C40-B> B0<

   }

}



void OnTick()

{

   //// '"+ + % (, 

   ////   1-3>   Open/Close/Modify =0 B8:

   ////   (", !  +!" #

   //// 2 ?5@2CN >G5@54L BUY/SELL/CLOSE 0 ?>B>< C65 2AQ ?@>G55

   

   // ?@8 =5>1E>48<>AB8 7025@H8BL 8=8F80;870F8N

   if (!inited) {

      // A2O7L 5ABL, B8:8 84CB

      // 4>25AB8 8=8F80;870F8N 4> =C6=>9 :>=48F88

      if (!PostInit()) {

         // =5 4>25;0AL

         Alert("2>B 65 1;8=...");

         ExpertRemove();

      } else {

         // 2 DoInit ?@>AB02;5= :>@@5:B=K9 ticket

         inited=true;

      }

      return;

   }

   

   serverTime=TimeCurrent();

   if (scheduledAction!=ACTION_NONE && scheduledAction!=ACTION_CLOSE && scheduledTimeout!=0 && serverTime>=scheduledTimeout) {

      // 459AB28O BUY/SELL 8<5NB B09<5@ 8 <>3CB M:A?09@8BAO

      scheduledAction=ACTION_NONE;

      scheduledTimeout=0;

   }

   // 2 4-:5 ?>;CG0BL B8: !  G5<C ;8H=85 42865=8O

   // Bid Ask 8 B0: ?@54>AB02;5=K 4;O OnTick 8;8 ?>A;5 RefreshRates

   // 0 2 5-:5 =C6=> 1C45B AG8B0BL B8:



   // 2AQ ?@>8=8G5=>, ticket 8;8 -1 5A;8 =5B =8D830 8;8 @50;L=> B8:5B

   

   bool allowActions=true;    // <>6=>-;8 2>>1I5 ?@>2>48BL B>@3>2K5 459AB28O

   if (Ask-Bid+_Point>=SPREAD*_Point) allowActions=false;   // =5 B>@3>20BL ?@8 1>;LH>< A?@545

   else if (NowNearM30()) allowActions=false;               // =5 B>@3>20BL =0 3@0=8F5 M30

   else if (NowMidnight()) allowActions=false;              // =5 B>@3>20BL >:>;> ?>;C=>G8

   

   ////   + ! ""

   if (ticket<0) {

      // =5B >B:@KBKE >@45@>2

      // <>65B >B:@KBL/?5@5>B:@KBL ?

      if (allowActions) {

         // ;N1K5 B>@3>2K5 459AB28O B>;L:> ?@8 <0;>< A?@545

         if (scheduledAction==ACTION_BUY || scheduledAction==ACTION_SELL) {

            if (OpenMyOrder(scheduledAction==ACTION_BUY?OP_BUY:OP_SELL)) {

               scheduledAction=ACTION_NONE;

               scheduledTimeout=0;

            }

            return;  // 2AQ, 70 B8: 1>;LH5 =5 CA?5BL

         }

      }

   } else {

      /// =865=0?8A0==>5 <>6=> ?5@5=>A8BL 2 A5:C=4=K9 B09<5@

      /// 0-;O OnSecond() - G0I5 @070 2 A5:C=4C 2AQ 2@O4-;8 =C6=>, 0 B8:8 <>3CB 1KAB@55

      if (!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) {

         // GB>-B> =5 B0: A A8=E@>=870F859, ?@>AB> ?@>?CAB8< B8:

         // 45;0BL =8G53> =5;L7O

         return;

      }

      if (OrderCloseTime()!=0) {

         // >@45@ 70:@K;AO @CG:0<8 8;8 ?> AB>?0</B59:0< (8;8 AB>?0CB, ?@8?;K;8)

         OnOrderClose();   // >1@01>B0BL, @07>1@0BLAO

         // 2 MB>B B8: 1>;LH5 =5 CA?5BL

         return;

      } else {

         // >@45@ >B:@KB

         if (allowActions) {

            if (OrderLots()>LOTS && AccountEquity()>maxBalance+SPREAD*LOTS*MarketInfo(_Symbol,MODE_TICKVALUE)) {

               if (CloseMyOrder()) {

                  scheduledAction=ACTION_NONE;

                  scheduledTimeout=0;

               }/* else {

                  scheduledAction=ACTION_CLOSE;

               }*/

               return;

            }

            // ;N1K5 B>@3>2K5 459AB28O B>;L:> ?@8 <0;>< A?@545

            if (scheduledAction==ACTION_CLOSE) {

               // ?;0=8@>20;>AL 70:@KB85 - 70:@KBL

               if (CloseMyOrder()) {

                  scheduledAction=ACTION_NONE;

                  scheduledTimeout=0;

               }

            } else {

               // 8=0G5 - ">1A;C68BL" >@45@

               ServeOrder();

            }

         }

      }

   }

   ////   + A  

   CheckForOnBar();

   ///  8 B0: 40;55...

   if (!hasTimer && TIMER_SECONDS>0) {

      if (!IsTesting() && !IsOptimization()) {

         hasTimer=EventSetTimer(TIMER_SECONDS);

      }

      if (TimeLocal()>=nextTimerLocalTime) {

         OnTimer();

         nextTimerLocalTime=TimeLocal()+TIMER_SECONDS;

      }

   }

}



// ">1A;C68BL" >B:@KBK9 >@45@

void ServeOrder()

{

   // ?@>25@O5< =5A@01>B:C SL/TP =0 35?0E 8 ?@>G8E 3;N:0E

   int type=OrderType();

   if (type==OP_BUY && (Bid>=virtualTakeProfit || Bid<=virtualStopLoss)) {

      scheduledAction=ACTION_CLOSE;

      return;

   } else

   if (type==OP_SELL && (Ask<=virtualTakeProfit || Ask>=virtualStopLoss)) {

      scheduledAction=ACTION_CLOSE;

      return;

   }

   if (scheduledAction!=ACTION_CLOSE) {

      // =5 =0<5@5205<AO 70:@K20BL

      // ?@>25@8BL =5 ?>@0 ;8 A>:@0I0BL 480?07>=

      if (serverTime>=OrderOpenTime()+HOLD_HOURS*60*60 &&

         iBarShift(_Symbol,PERIOD_M1,OrderOpenTime())>=HOLD_HOURS*60 && !OrderIsHolded()) {

            // 

            HoldOrder();

      }

      // A8=E@>=87C5< 28@BC0;L=K5 Tp/Sl

      if (OrderLots()==LOTS) {

      if ((OrderStopLoss()!=virtualStopLoss || OrderTakeProfit()!=virtualTakeProfit)) {

         if (!OrderModify(ticket,OrderOpenPrice(),virtualStopLoss,virtualTakeProfit,0)) {

            int err=GetLastError();

            PrintFormat("Unable sync virtual SL/TP error=%d %s",err,ErrorDescription(err));   

         }

      }

      }

   }

}



void OnTimer()

{

   // B8:8 7025@H05< 1KAB@>-1KAB@>, ?>MB><C >B:@KB8O 10@>2 4>?>;=8B5;L=> ?@>25@O5< ?> B09<5@C

   serverTime=TimeCurrent();

   if (serverTime>=nextDayTime) {

      OnDay();

      OnM30();

   } else if (serverTime>=nextM30) {

      OnM30();

   }

   CheckForOnBar();

}

void OnM30()

{

   m30Time=iTime(_Symbol,PERIOD_M30,0);   // 2 @50;5 - 2K@02=820BL

   nextM30=m30Time+30*60;

}

bool NowNearM30()

{

   if (serverTime<=m30Time+SEC_AFTER_M30 ||

      serverTime>=nextM30-SEC_BEFORE_M30) {

      return true;

   }

   return false;

}

void OnDay()

{

   serverTime=TimeCurrent();

   MqlDateTime dt; TimeToStruct(serverTime,dt);

   dt.hour=0;

   dt.min=0;

   dt.sec=0;

   dayTime=StructToTime(dt);

   nextDayTime=dayTime+24*60*60;

}



bool NowMidnight() 

{

   if (serverTime<=dayTime+MINUTES_AFTER_MIDNIGHT*60 ||

      serverTime>=nextDayTime-MINUTES_BEFORE_MIDNIGHT*60) {

      return true;

   } 

   return false;

}



// GB> 45;05< ?@8 >B:@KB88 10@0

void OnBar()

{

   if (ticket>=0) {

      // 5A;8 5ABL >B:@KBK9 B8:5B, B> =8G53>

      return;

   }



   if (NowMidnight()) {

      // 2 ?>;=>G=>5 2@5<O - A83=0;K 83=>@8@CNBAO

      return;

   }

   // 15@Q< B>@3>2K9 A83=0; 8 ?> =5<C B>@3C5<

   int signal=GetSignal();

   if (signal==OP_BUY) {

      scheduledAction=ACTION_BUY;

      scheduledTimeout=serverTime+BUYSELL_TIMEOUT;

   }

   else if (signal==OP_SELL) {

      scheduledAction=ACTION_SELL;

      scheduledTimeout=serverTime+BUYSELL_TIMEOUT;

   }

}



////////////////////

/// !83=0;L=0O G0ABL

////////////////////



void CheckForOnBar()

{

   if (serverTime>=nextBarTime) {

      datetime tmp=iTime(_Symbol,TIMEFRAME,0);

      if (tmp!=barTime) {

         barTime=tmp;

         nextBarTime=barTime+PeriodSeconds(); // FIXME: =5<=>3> =525@=>, 4;O @50;0 =04> 2K@02=820BL

         OnBar();

      }

   }

}



////////////////////////////

// #'"    +"   

///////////////////////////

void OnOrderClose() 

{

   double orderProfit=OrderProfit()+OrderSwap()+OrderCommission();

   double orderPoints=MathAbs(OrderOpenPrice()-OrderClosePrice())/_Point;

   double tickValue=MarketInfo(_Symbol,MODE_TICKVALUE);

   if (orderProfit>=0) {

      // 70:@KB A ?@>D8B><

      double nominal=(TP+SPREAD)*LOTS*tickValue; // =><8=0;L=0O (157 @0AH.480?07>=0 8 <0@B8=0) ?@81K;L >B >@45@0

      double hover=OrderProfit()-nominal; // ?@81K;L A25@E =><8=0;0

      if (orderPoints>pointsTakeProfit/2.0) {

         // 70:@KB> >1KG=K< >1@07><

         credit-=hover;                        // 2AQ GB> A25@E =><8=0;0 A?8AK205< A credit

         PrintFormat("====== step=0"); 

      } else {

         credit-=orderProfit;  // 2AQ A?8AK205BAO A credit, H03>2 =5 45;05<

         PrintFormat("====== hold step=%d",step); 

         //if (credit<=0.01) credit=LOTS*SPREAD*tickValue;

      }

      PrintFormat("====== Close with PROFIT %f, nominal=%f credit=%f hover=%f",orderProfit,nominal,credit);

   } else {

      double nominal=(SL-SPREAD)*LOTS*tickValue; // =><8=0;L=K9 C1KB>: >B >@45@0

      double hover=-(nominal+orderProfit);

      if (orderPoints>pointsStopLoss/2.0) {

         // 70:@KB> >1KG=K< >1@07><

         credit+=hover;                        // 2AQ GB> A25@E =><8=0;0 4>102;O5< 2 credit

      } else {

         // 70:@KB> @C:0<8 8;8 HOLD

         credit+=-orderProfit;

      }

      PrintFormat("====== Close with LOSS %f, nominal=%f credit=%f hover=%f",orderProfit,nominal,credit);

   }

   //if (credit<0) credit=0;

   currBalance=AccountBalance();

   if (currBalance>=maxBalance) {

      // 2KH;8 87 ?@>A04:8

      minBalance=currBalance;

      maxBalance=currBalance;

      // >1=C;O5< 2A5 4>;38 (5A;8 5ABL)

      //if (credit>0) credit=LOTS*SPREAD*tickValue;

      credit=LOTS*SPREAD*tickValue;

      step=0;

   } else if (maxBalance>initialBalance && currBalance<initialBalance ) {

         maxBalance=minBalance=initialBalance;

         if (OrderLots()==LOTS) credit=LOTS*SPREAD*tickValue;

   } else {

      if (currBalance<minBalance) {

         minBalance=currBalance;

      }

   }

   ticket=-1;

   virtualStopLoss=0;

   virtualTakeProfit=0;

   pointsStopLoss=0;

   pointsTakeProfit=0;

}

bool CloseMyOrder()

{

   if (ticket<0) return true;

   bool ok=OrderClose(ticket,OrderLots(),OrderType()==OP_BUY?Bid:Ask,1);

   if (ok) {

      OnOrderClose();

   }

   return ok;

}

bool OpenMyOrder(int type)

{

   // @0AAGQB >1JQ<0 >@45@0 8 ?C=:B>2 TP/SL

   double lotStep=MarketInfo(_Symbol,MODE_LOTSTEP);

   double minLot=MarketInfo(_Symbol,MODE_MINLOT);

   double maxLot=MarketInfo(_Symbol,MODE_MAXLOT);

   double tickValue=MarketInfo(_Symbol,MODE_TICKVALUE);

   

   double spreadMoney=SPREAD*LOTS*tickValue; // F5=0 A?@540

   double stepMoney=(1+STEPS)*spreadMoney; // AC<<0 ?@>3@5AA88 1+2+..+STEPS *2  2 45=L30E

   double martinMoney=0;      // AB>;L:> =04> >B18BL G5@57 <0@B8=

   pointsStopLoss=SL;

   pointsTakeProfit=TP;

   if (credit>spreadMoney*START_STEP) {

      if (credit<=stepMoney) {

         pointsStopLoss=(int)(SL+MathRound(stepMoney/(SPREAD*LOTS*tickValue)));

         pointsTakeProfit=(int)(TP+MathRound(stepMoney/(SPREAD*LOTS*tickValue)));

      } else {

         pointsStopLoss=SL+SPREAD*STEPS;

         pointsTakeProfit=TP+SPREAD*STEPS;

         // 70 pointsTakeProfit =04> >B18BL A@07C:

         // - 8 @0=55 ?>;CG5==K5 C1KB:8, ?> :@09=59 <5@5 = credit-stepMoney+spreadMoney

         // - 8 =>2>>1@07>20==K9 A?@54

         // x * (pointsTakeProfit-spread) * tickValue = x * SPREAD *tickValue + credit-stepMoney+spreadMoney

         // x = (credit - stepMoney + spreadMoneya) / ((pointsTakeProfit - 2 *spread)*tickValue)

         martinMoney = credit-stepMoney*2/3+spreadMoney;//credit-stepMoney/2+spreadMoney);

//         martinMoney = credit;

         PrintFormat("martinMoney=%f",martinMoney);

         //martinMoney=((credit-stepMoney)+spreadMoney*2)*(1+TP*1.0/SPREAD);//*MathMax(STEPS/2.0,3);

      }

   }

   double lots=NormalizeLots(LOTS,minLot,maxLot,lotStep);

   if (martinMoney>0) {

      // 70 pointsTakeProfit =04> >B18BL A@07C:

      // - 8 @0=55 ?>;CG5==K5 C1KB:8, ?> :@09=59 <5@5 = credit-stepMoney+spreadMoney

      // - 8 =>2>>1@07>20==K9 A?@54

      // x * (pointsTakeProfit-spread) * tickValue = x * SPREAD *tickValue + credit-stepMoney+spreadMoney

      // x = (credit - stepMoney + spreadMoneya) / ((pointsTakeProfit - 2 *spread)*tickValue)

      double martinLots = martinMoney / ( ((pointsTakeProfit - 2 * SPREAD) *tickValue) );

      PrintFormat("martinLots=%f",martinLots);

      //martinMoney=((credit-stepMoney)+spreadMoney*2)*(1+TP*1.0/SPREAD);//*MathMax(STEPS/2.0,3);

      if (martinLots<lotStep) lots=NormalizeLots(lots+lotStep,minLot,maxLot,lotStep);

      else lots=NormalizeLots(lots+martinLots,minLot,maxLot,lotStep);

      //lots=NormalizeLots(LOTS+addon+minLot/2.0,minLot,maxLot,lotStep);

   }

   

   int tt=OrderSend(_Symbol,type,lots,type==OP_BUY?Ask:Bid,0,0,0,"",MAGIC);

   if (tt>=0) {

      // >@45@ >B:@K;AO

      if (OrderSelect(tt,SELECT_BY_TICKET,MODE_TRADES)) {

         if (type==OP_BUY) {

            virtualTakeProfit=NormalizeDouble(OrderOpenPrice()+pointsTakeProfit*_Point,_Digits);

            virtualStopLoss=NormalizeDouble(OrderOpenPrice()-pointsStopLoss*_Point,_Digits);

         } else {

            virtualTakeProfit=NormalizeDouble(OrderOpenPrice()-pointsTakeProfit*_Point,_Digits);

            virtualStopLoss=NormalizeDouble(OrderOpenPrice()+pointsStopLoss*_Point,_Digits);

         }

      }

      ticket=tt;

   }

   return (tt>=0);

}

bool OrderIsHolded()

{

   if (OrderType()==OP_BUY) {

      double level=OrderOpenPrice()+2*SPREAD*_Point; // C@>25=L 157C1KB:0+A?@54

      if (virtualTakeProfit<=level || virtualStopLoss>=level) return true;

   } else {

      double level=OrderOpenPrice()-2*SPREAD*_Point; // C@>25=L 157C1KB:0+A?@54

      if (virtualTakeProfit>=OrderOpenPrice() || virtualStopLoss<=level) return true;

   }

   return false;

}

// A>:@0B8BL B>@3>2K9 480?07>= >@45@0

// 5A;8 >= 2 ?@81K;8 - ?5@5=5AB8 takeprofit =0 F5=C >B:@KB8O

// 5A;8 2 C1KB:5 - AB>?-;>AA BC40-65

// => A> A?@54><, A?@54 =04> 7018@0BL >1@0B=> 

bool HoldOrder()

{

   if (OrderType()==OP_BUY) {

      double level=NormalizeDouble(OrderOpenPrice()+2*SPREAD*_Point,_Digits); // C@>25=L 157C1KB:0+A?@54

      if (Bid>=level) {

         virtualStopLoss=level;

         return true;

      } else  {

         virtualTakeProfit=level;

         return true;

      }    

   } else {

      double level=NormalizeDouble(OrderOpenPrice()-2*SPREAD*_Point,_Digits); // C@>25=L 157C1KB:0+A?@54

      if (Ask<=level) {

         virtualStopLoss=level;

         return true;

      } else  {

         virtualTakeProfit=level;

         return true;

      }    

   }

   return false;

}



double NormalizeLots(double lots,double minLot=0,double maxLot=0,double lotStep=0)

{

   if (minLot==0) minLot=MarketInfo(_Symbol,MODE_MINLOT);

   if (maxLot==0) maxLot=MarketInfo(_Symbol,MODE_MAXLOT);

   if (lotStep==0) lotStep=MarketInfo(_Symbol,MODE_LOTSTEP);

   if (lots<=minLot) return minLot;

   lots=minLot+MathRound((lots-minLot)/lotStep)*lotStep;

   if (lots>=maxLot) return maxLot;

   return lots;

}

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---