HYROLEAN

test_3ma_user.mq4

Mar 16th, 2025 (edited)
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 48.68 KB | Money | 0 0
  1. #property copyright "2024-2025, (c)hyrolean"
  2. #property link      "https://pastebin.com/6jvBeEfi"
  3. #property version   "1.00"
  4. #property strict
  5.  
  6. #include <stdlib.mqh>
  7.  
  8. /*
  9.  
  10.  New 3EMA 手法 ( 状態遷移情報をターミナルに格納する変数を必要としないバージョン )
  11.  
  12.  ・ 建玉するときに、EMA50をストップロスに設定する(Stoploss=0の場合)
  13.  
  14.     ※ 現在価格がEMA50を下回るところでは、建玉を行わないようにする
  15.  
  16.  ・ ストップロスが玉の価格より下にあるものに的を絞り、EMA50を基準にトレーリングを行う
  17.  
  18.     ※ ただし、玉の価格がEMA50より下にある場合は、上記の操作を見送ることとする
  19.  
  20.  ・ ストップロスが玉の価格より下にあるものに的を絞り、ロウソク足が5期間経過後から、
  21.    現在のプライスが超えた時点でストップロスをエントリープライスに移動し、ロットの1/3を利確する
  22.  
  23.    ロウソク足の期間の出し方: (Time[0]-OrderOpenTime())/(Period()*60)>=5
  24.  
  25.     ※ 5期間経過後に未だ現価が下にある場合は、現価が上に来るまでこの試行は継続
  26.       されることとし、現価がロウソク足1期間でも抜けたら即ストップロスをエントリープライスに移動
  27.       し、ロットの1/3利確することとする
  28.  
  29.  ・ 現在価格がEMA10を下回った場合、ストップロスがエントリープライスに一致する玉を検出し、
  30.    EMA20の位置にストップロスを移動し、ロットの1/2を利確する(この時点でEMA20も現在価格
  31.    を突破している場合は、全ロットを利確することとする)
  32.  
  33.     ※ ただし、玉の価格がEMA20より上にある場合は、上記の操作を見送ることとする
  34.  
  35.  ・ ストップロスが玉の価格より上にあるものに的を絞り、EMA20を基準にトレーリングを行う
  36.  
  37. */
  38.  
  39. /*
  40.  
  41.   使い方::
  42.  
  43.   左上の|SELL|BUY|ボタンを選んでポジションを自分で打ちます。
  44.   ポジションを打ったら、sl(ストップロス)のBARを自分の好みの場所に移動させます。
  45.   以降、3EMAの手法に従って自動的に利確されます。(逆行しなければですが…)
  46.   運悪く逆行してしまった場合は、損益の㌫、または、slに応じて自動損切されます。
  47.  
  48.   エントリーのコツとしては、上から現在価格,EMA10,EMA20,EMA50の順番で並んでいるときは、
  49.   ロング(買い)、逆に、上からEMA50,EMA20,EMA10,現在価格の順番で並んでいるときは、
  50.   ショート(売り)でエントリーすると上手くいくかもしれないです。
  51.  
  52.   (利確のタイミングを図りたい場合など、自動処理を一時的に中断したい場合は、Automate
  53.   Processing Orders をfalseに設定すると無効に出来ます。)
  54.  
  55.   MT4を閉じてもslとエントリープライスの位置だけで状態を把握する為、万が一VPS等が停止し
  56.   てしまってもサーバー側に建玉の情報さえ残っていればMT4を再度立ち上げてこのEAを有
  57.   効化するだけで状態復帰可能な仕様に仕上げています。
  58.  
  59.   youtubeで手法を解説している動画等::
  60.  
  61.       https://youtu.be/GsAAMgKXzic
  62.       https://youtu.be/XUqDyupYGdk
  63.  
  64.   以上ゞ
  65.  
  66. */
  67.  
  68. #define ENTRY_NAME "3MAUser"
  69.  
  70. enum ENUM_POSI {
  71.   POSI_STOP,                  // Stop
  72.   POSI_ONLY_LONG,             // Only Long
  73.   POSI_ONLY_SHORT,            // Only Short
  74.   POSI_HALF_LONG_AND_SHORT,   // Long & Short (Half duplex)
  75.   POSI_FULL_LONG_AND_SHORT    // Long & Short (Full duplex)
  76. };
  77.  
  78. enum ENUM_TIMEBASE {
  79.   TIMEBASE_GMT,               // Greenwich Mean Time (GMT)
  80.   TIMEBASE_LOCAL,             // Local Time
  81.   TIMEBASE_SERVER             // Server Time
  82. };
  83.  
  84. enum ENUM_TIMEACT {
  85.   TIMEACT_NONE,               // None ( EA closes positions automatically )
  86.   TIMEACT_FORCE_CLOSE_ALL,    // Force Close All positions
  87.   TIMEACT_FORCE_CLOSE_LONG,   // Force Close Long positions
  88.   TIMEACT_FORCE_CLOSE_SHORT,  // Force Close Short positions
  89.   TIMEACT_SOFT_CLOSE_ALL,     // Close All positions if profits are Positive
  90.   TIMEACT_SOFT_CLOSE_LONG,    // Close Long positions if profits are Positive
  91.   TIMEACT_SOFT_CLOSE_SHORT    // Close Short positions if profits are Positive
  92. };
  93.  
  94. input bool      Automation      = true;     // Automate processing orders
  95. input ENUM_TIMEFRAMES MainTimeFrame = PERIOD_CURRENT; // Main Time Frame
  96. input int MAGICMA               = 0;        // Magic Number
  97. input bool      TimeControl     = false;    // Time Control
  98. input ENUM_TIMEBASE TimeBase    = TIMEBASE_LOCAL; // Time Base
  99. input string    TimeStart       = "09:00";  // Time Start
  100. input string    TimeEnd         = "15:00";  // Time End
  101. input ENUM_TIMEACT TimeAction   = TIMEACT_NONE; // Time Action when time end reached
  102. input ENUM_MA_METHOD      MAMode= MODE_EMA; // MA mode
  103. input ENUM_APPLIED_PRICE  MAPriceType = PRICE_CLOSE; // MA price type
  104. input bool      MA3             = true;     // 3MA Enabled
  105. input int       MA3FastPeriod   = 10;       // 3MA Fast period
  106. input int       MA3MediumPeriod = 20;       // 3MA Medium period
  107. input int       MA3SlowPeriod   = 50;       // 3MA Slow period
  108. input int       MA3TLPeriod     = 5;        // 3MA TL(TimeLimited) period
  109. input int       Slippage        = 10;       // Max Slippage
  110. input int       Spread          = 50;       // Max Spread in points
  111. input double    BaseLots        = 0.1;      // Base Lots
  112. input double    StepLots        = 0.01;     // Step Lots
  113. input double    MinLots         = 0.01;     // Minimum Lots
  114. input double    MaxLots         = 50.0;     // Maximum Lots
  115. input double    LotsDenomTL     = 3.0;      // Lots denom of 3MA TL(TimeLimited)
  116. input double    LotsDenomMAFast = 2.0;      // Lots denom of 3MA Fast MA
  117. input double    Takeprofit      = 0;        // Take profit in points (0 = unlimited)
  118. input double    Stoploss        = 200;      // Stop loss in points (0 = Grossloss per or SlowMA trail)
  119. input double    MaxGrosslossPer = 25;       // Maximum Allowed Gross loss of Balance in percentage
  120. input bool      Compounding     = false;    // Compounding interest Enabled
  121. input double    CompoundingBase = 100000;   // Compounding Base Balance (Lots=BaseLots*Balance/BaseBalance)
  122. input bool      BalanceIncludeCredit= true; // Balance include Credit
  123. input bool      Trailing        = false;    // Trailing Enabled
  124. input double    TrailingStart   = 300;      // Trailing Start in points
  125. input double    TrailingStop    = 200;      // Trailing Stop in points
  126. input bool      ShowUserEntry   = true;     // Show user entry SELL/BUY buttons
  127. input bool      ShowCloseAll    = true;     // Show a CLOSE ALL button
  128. input bool      ShowCloseLong   = false;    // Show a CLOSE LONG button
  129. input bool      ShowCloseShort  = false;    // Show a CLOSE SHORT button
  130. input bool      ShowFlushTL     = true;     // Show a FLUSH TL button
  131. input bool      ShowAmount      = true;     // Show Current Amount
  132. input int       AmountDig       = 0;        // Amount Number of decimal places
  133. input color     ClrAmountPosi   = clrLightGoldenrod; // Amount Positive color
  134. input color     ClrAmountNega   = clrLightPink; // Amount Negative color
  135. input color     ClrTimeControl  = clrYellow; // Time Control Status color
  136. input color     ClrLongArrow    = clrBlue;  // Long Arrow color
  137. input color     ClrShortArrow   = clrRed;   // Short Arrow color
  138. input bool      DBGMODE         = true;     // DEBUG MODE
  139.  
  140. double Lots, PrevBid, PrevAsk;
  141.  
  142. #define MAShift 0
  143.  
  144. datetime CurTime, TimeTick, StartTime, CancelTime, UserTime;
  145.  
  146. #define ORDER_RETRY  10
  147.  
  148. #define FLAG_BUY      1
  149. #define FLAG_SELL     2
  150. #define FLAG_DUPLEX   4
  151.  
  152. int UserEntry = 0 ;
  153. bool FlushTL = false ;
  154.  
  155. #define SELLBTN_NAME       "EntrySell"
  156. #define BUYBTN_NAME        "EntryBuy"
  157. #define CLOSEALLBTN_NAME   "CloseAll"
  158. #define CLOSELONGBTN_NAME  "CloseLong"
  159. #define CLOSESHORTBTN_NAME "CloseShort"
  160. #define FLUSHTLBTN_NAME    "FlushTL"
  161.  
  162. #define OFFTIME_NAME "OFF TIME"
  163. bool OffTimeVisible = false ;
  164.  
  165. #define AMOUNT_NAME "AMOUNT"
  166. #define AMOUNT_CLR_NEGA  ClrAmountNega
  167. #define AMOUNT_CLR_POSI  ClrAmountPosi
  168.  
  169. #define DBGINFO_NAME "DEBUG INFO"
  170.  
  171.   bool InnerPoint(double v, double comp) {
  172.     return comp-Point/2.0 < v && v < comp+Point/2.0 ;
  173.   }
  174.  
  175.   double AdjLots(double lots) {
  176.     double roundLots = MathRound( MathMax(lots,StepLots) / StepLots ) ;
  177.     return MathMin(MathMax(roundLots*StepLots,MinLots),MaxLots) ;
  178.   }
  179.  
  180. //---------------------------------------------------------------------------
  181. //エラーログ出力
  182. void PrintLastError()
  183. {
  184.   int lastError = GetLastError() ;
  185.   printf(ENTRY_NAME"(%s): error(%d): %s",
  186.     Symbol(),lastError,ErrorDescription(lastError));
  187. }
  188. //---------------------------------------------------------------------------
  189. //メッセージ出力
  190. void PrintMessage(string message)
  191. {
  192.   printf(ENTRY_NAME"(%s): %s",Symbol(),message);
  193. }
  194. //---------------------------------------------------------------------------
  195. //オブジェクトのソート
  196. // ( https://youtu.be/ZRPiwUNLjiA )
  197. #include <Arrays/ArrayObj.mqh>
  198. #define ARRAY_SORT_ASCEND 1
  199. #define ARRAY_SORT_DESCEND 2
  200. template <typename T>
  201. class CSortable : public CObject {
  202. public:
  203.     T key;
  204.     int Compare(const CObject *node, const int mode=0) const {
  205.       if(mode<=0) return 0;
  206.       CSortable *comp= (CSortable*)node ;
  207.       bool f = key<comp.key ;
  208.       if(!f&&!(comp.key<key)) return 0;
  209.       int result = f ? -1:+1 ;
  210.       switch(mode) {
  211.         case ARRAY_SORT_ASCEND:  return +result;
  212.         case ARRAY_SORT_DESCEND: return -result;
  213.       }
  214.       return 0;
  215.     }
  216. };
  217. template <typename T>
  218. void AddToArray(CArrayObj &array, const T& key) {
  219.   CSortable<T> *node = new CSortable<T>();
  220.   node.key=key;
  221.   array.Add(node);
  222. }
  223. //---------------------------------------------------------------------------
  224. int OnInit()
  225. {
  226.   //テスターで表示されるインジケータを非表示にする
  227.   HideTestIndicators(!DBGMODE);
  228.  
  229.   CurTime = MainTime();
  230.   TimeTick = CancelTime = StartTime = UserTime = BaseTime();
  231.  
  232.   Lots = AdjLots(BaseLots) ; PrevBid = Bid ; PrevAsk = Ask ;
  233.  
  234.   //DEBUG INFO
  235.   if(DBGMODE) {
  236.     ObjectCreate(DBGINFO_NAME, OBJ_LABEL, 0, 0, 0);
  237.     ObjectSet(DBGINFO_NAME, OBJPROP_XDISTANCE, 10);
  238.     ObjectSet(DBGINFO_NAME, OBJPROP_YDISTANCE, 15);
  239.     ObjectSet(DBGINFO_NAME, OBJPROP_CORNER, 3);
  240.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, "DEBUG INFO");
  241.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_FONT, "Verdana");
  242.     ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_FONTSIZE, 8);
  243.     ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_COLOR, clrAquamarine);
  244.   }
  245.  
  246.   //金額表示
  247.   if(ShowAmount) {
  248.     ObjectCreate(AMOUNT_NAME, OBJ_LABEL, 0, 0, 0);
  249.     ObjectSet(AMOUNT_NAME, OBJPROP_XDISTANCE, 20);
  250.     ObjectSet(AMOUNT_NAME, OBJPROP_YDISTANCE, 35);
  251.     ObjectSet(AMOUNT_NAME, OBJPROP_CORNER, 3);
  252.     ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, "0-");
  253.     ObjectSetString(0, AMOUNT_NAME, OBJPROP_FONT, "Verdana");
  254.     ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_FONTSIZE, 15);
  255.     ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
  256.   }
  257.  
  258.   //ユーザーエントリ用ボタン
  259.   if(ShowUserEntry) {
  260.  
  261.     //SELLボタン
  262.     ObjectCreate(SELLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  263.     ObjectSet(SELLBTN_NAME, OBJPROP_XDISTANCE, 10);
  264.     ObjectSet(SELLBTN_NAME, OBJPROP_YDISTANCE, 20);
  265.     ObjectSet(SELLBTN_NAME, OBJPROP_XSIZE, 58);
  266.     ObjectSet(SELLBTN_NAME, OBJPROP_YSIZE, 32);
  267.     ObjectSet(SELLBTN_NAME, OBJPROP_CORNER, 0);
  268.     ObjectSet(SELLBTN_NAME, OBJPROP_FONTSIZE, 12);
  269.     ObjectSet(SELLBTN_NAME, OBJPROP_COLOR, White);
  270.     ObjectSet(SELLBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
  271.     ObjectSetString(0, SELLBTN_NAME, OBJPROP_TEXT, "SELL");
  272.     ObjectSetString(0, SELLBTN_NAME, OBJPROP_FONT, "Verdana");
  273.  
  274.     //BUYボタン
  275.     ObjectCreate(BUYBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  276.     ObjectSet(BUYBTN_NAME, OBJPROP_XDISTANCE, 70);
  277.     ObjectSet(BUYBTN_NAME, OBJPROP_YDISTANCE, 20);
  278.     ObjectSet(BUYBTN_NAME, OBJPROP_XSIZE, 58);
  279.     ObjectSet(BUYBTN_NAME, OBJPROP_YSIZE, 32);
  280.     ObjectSet(BUYBTN_NAME, OBJPROP_CORNER, 0);
  281.     ObjectSet(BUYBTN_NAME, OBJPROP_FONTSIZE, 12);
  282.     ObjectSet(BUYBTN_NAME, OBJPROP_COLOR, White);
  283.     ObjectSet(BUYBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
  284.     ObjectSetString(0, BUYBTN_NAME, OBJPROP_TEXT, "BUY");
  285.     ObjectSetString(0, BUYBTN_NAME, OBJPROP_FONT, "Verdana");
  286.  
  287.   }
  288.  
  289.   int btn_ofs_x = 0 ;
  290.   const int btn_distance = 102 ;
  291.  
  292.   //全決済ボタン
  293.   if(ShowCloseAll) {
  294.     ObjectCreate(CLOSEALLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  295.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  296.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YDISTANCE, 35);
  297.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XSIZE, 100);
  298.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YSIZE, 25);
  299.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_CORNER, 2);
  300.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_FONTSIZE, 10);
  301.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_COLOR, White);
  302.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_BGCOLOR, /*clrDarkGreen*/clrDarkSlateGray);
  303.     ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_TEXT, "CLOSE ALL");
  304.     ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_FONT, "Verdana");
  305.     btn_ofs_x += btn_distance ;
  306.   }
  307.  
  308.   //LONG決済ボタン
  309.   if(ShowCloseLong) {
  310.     ObjectCreate(CLOSELONGBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  311.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  312.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YDISTANCE, 35);
  313.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XSIZE, 100);
  314.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YSIZE, 25);
  315.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_CORNER, 2);
  316.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_FONTSIZE, 10);
  317.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_COLOR, White);
  318.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
  319.     ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_TEXT, "CLOSE LONG");
  320.     ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_FONT, "Verdana");
  321.     btn_ofs_x += btn_distance ;
  322.   }
  323.  
  324.   //SHORT決済ボタン
  325.   if(ShowCloseShort) {
  326.     ObjectCreate(CLOSESHORTBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  327.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  328.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YDISTANCE, 35);
  329.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XSIZE, 100);
  330.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YSIZE, 25);
  331.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_CORNER, 2);
  332.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_FONTSIZE, 10);
  333.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_COLOR, White);
  334.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
  335.     ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_TEXT, "CLOSE SHORT");
  336.     ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_FONT, "Verdana");
  337.     btn_ofs_x += btn_distance ;
  338.   }
  339.  
  340.   //TLフラッシュ決算ボタン
  341.   if(ShowFlushTL) {
  342.     ObjectCreate(FLUSHTLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  343.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  344.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_YDISTANCE, 35);
  345.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_XSIZE, 100);
  346.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_YSIZE, 25);
  347.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_CORNER, 2);
  348.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_FONTSIZE, 10);
  349.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_COLOR, White);
  350.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_BGCOLOR, clrDarkSlateBlue);
  351.     ObjectSetString(0, FLUSHTLBTN_NAME, OBJPROP_TEXT, "FLUSH TL");
  352.     ObjectSetString(0, FLUSHTLBTN_NAME, OBJPROP_FONT, "Verdana");
  353.     btn_ofs_x += btn_distance ;
  354.  
  355.   }
  356.  
  357.   //ユーザーエントリをリセット
  358.   UserEntry=0;
  359.  
  360.   return(INIT_SUCCEEDED);
  361. }
  362. //---------------------------------------------------------------------------
  363. void OnDeinit(const int reason)
  364. {
  365.   if(ShowFlushTL) ObjectDelete(FLUSHTLBTN_NAME);
  366.   if(ShowCloseShort) ObjectDelete(CLOSESHORTBTN_NAME) ;
  367.   if(ShowCloseLong) ObjectDelete(CLOSELONGBTN_NAME) ;
  368.   if(ShowCloseAll) ObjectDelete(CLOSEALLBTN_NAME) ;
  369.   if(ShowUserEntry) {
  370.     ObjectDelete(BUYBTN_NAME) ;
  371.     ObjectDelete(SELLBTN_NAME) ;
  372.   }
  373.   if(OffTimeVisible) {
  374.     ObjectDelete(OFFTIME_NAME) ;
  375.     OffTimeVisible=false ;
  376.   }
  377.   if(ShowAmount) {
  378.     ObjectDelete(AMOUNT_NAME) ;
  379.   }
  380.   if(DBGMODE) {
  381.     ObjectDelete(DBGINFO_NAME) ;
  382.   }
  383. }
  384. //---------------------------------------------------------------------------
  385. void OnTick()
  386. {
  387.   datetime nextTime = MainTime() ;
  388.   bool nextTimed = nextTime != CurTime ;
  389.   CurTime = nextTime ;
  390.  
  391.   datetime nextTick = BaseTime() ;
  392.   bool nextTicked = nextTick != TimeTick ;
  393.   TimeTick = nextTick;
  394.  
  395.   // タイムコントロールチェック
  396.   CheckTimeControl(nextTicked);
  397.  
  398.   // 動作チェック
  399.   CheckBehavior(nextTimed);
  400.  
  401.   double atr14 = iATR(NULL,0,14,0) ;
  402.   double spread = Ask-Bid ;
  403.  
  404.   // デバッグ欄表示のサンプル
  405.   if(DBGMODE) {
  406.     DBGOUT(
  407.       // ATR in points
  408.       StringFormat("ATR(14): %.3f",atr14/Point) + " | " +
  409.       // SPREAD in points
  410.       StringFormat("SPREAD: %g",spread/Point) + " | " +
  411.       // 現在の値幅の変動倍率(ATR/SPREAD)
  412.       StringFormat("ATR(14)/SPREAD: %.3f",atr14/(spread<=0?1:spread))
  413.     );
  414.   }
  415.  
  416.   // エントリー処理
  417.   if(IsExpertEnabled()&&IsTradeAllowed()) {
  418.  
  419.     int busy = AlreadyOrdered(FLAG_BUY|FLAG_SELL,MAGICMA) ;
  420.  
  421.     // ユーザーの注文
  422.     if(UserEntry) {
  423.  
  424.       // ユーザーのエントリを確認
  425.       if(TimeTick-UserTime<60) {  // 発行されてから60秒以内の注文
  426.  
  427.         int user = UserEntry ;
  428.  
  429.         // 注文
  430.         if(user/*&&!AlreadyOrdered(user,MAGICMA)*/) {
  431.  
  432.           int entry = user == FLAG_BUY ? OP_BUY : OP_SELL ;
  433.           if(EntryManualPosition("USER", entry, Lots)>=0)
  434.           {  busy |= user ; UserEntry = 0 ; }
  435.         }
  436.  
  437.       }else { UserEntry=0; }
  438.  
  439.     }
  440.  
  441.     // MARK: 自動注文
  442.  
  443.     /*
  444.     do {
  445.  
  446.       // 自動注文 開始時間調整
  447.       if(StartTime>TimeTick||CancelTime>TimeTick)
  448.         break ;
  449.  
  450.       // スプレッド幅のチェック
  451.       if(MarketInfo(NULL,MODE_SPREAD) > Spread)
  452.         break ;
  453.  
  454.       // 自動注文 XMA+ZigZag Detector
  455.       if(nextTimed)
  456.         EAEntryXMAZigZagPosition(busy,1);
  457.  
  458.     }while(0);
  459.     */
  460.  
  461.   }else {
  462.  
  463.     if(StartTime-TimeTick<10)
  464.       StartTime = TimeTick+10 ;
  465.  
  466.   }
  467.  
  468.   /*
  469.   if(PmdTiming) {
  470.     PmdPrevBid = (PmdPrevBid+Bid)/2.0 ; PmdPrevAsk = (PmdPrevAsk+Ask)/2.0 ;
  471.   }*/
  472.   PrevBid = Bid ; PrevAsk = Ask ;
  473. }
  474. //---------------------------------------------------------------------------
  475. void OnChartEvent(
  476.   const int id,
  477.   const long &lparam,
  478.   const double &dparam,
  479.   const string &sparam
  480.  )
  481. {
  482.   if( ( sparam == CLOSEALLBTN_NAME ||
  483.         sparam == CLOSELONGBTN_NAME ||
  484.         sparam == CLOSESHORTBTN_NAME ) && id==CHARTEVENT_OBJECT_CLICK) {
  485.     int orderFlag = 0 ;
  486.     if(sparam == CLOSEALLBTN_NAME) orderFlag = FLAG_SELL | FLAG_BUY ;
  487.     else if(sparam == CLOSELONGBTN_NAME) orderFlag = FLAG_BUY ;
  488.     else if(sparam == CLOSESHORTBTN_NAME) orderFlag = FLAG_SELL ;
  489.     CheckoutOrderAll(orderFlag);
  490.     Sleep(100);
  491.     ObjectSet(sparam, OBJPROP_STATE, False);
  492.     // 60秒エントリーを停止する
  493.     CancelTime = TimeTick + 60 ;
  494.   }
  495.   if(sparam == FLUSHTLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  496.     FlushTL=true;
  497.     Sleep(100);
  498.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_STATE, False);
  499.   }
  500.   if(sparam == SELLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  501.     { UserEntry = FLAG_SELL ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
  502.     Sleep(100);
  503.     ObjectSet(SELLBTN_NAME, OBJPROP_STATE, False);
  504.   }
  505.   if(sparam == BUYBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  506.     { UserEntry = FLAG_BUY ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
  507.     Sleep(100);
  508.     ObjectSet(BUYBTN_NAME, OBJPROP_STATE, False);
  509.   }
  510. }
  511. //---------------------------------------------------------------------------
  512. //DBGOUT
  513. void DBGOUT(string text)
  514. {
  515.   if(DBGMODE) {
  516.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, text);
  517.   }
  518. }
  519. //---------------------------------------------------------------------------
  520. //タイムコントロールチェック
  521. void CheckTimeControl(bool nextTicked)
  522. {
  523.   if(!TimeControl) {
  524.     if(OffTimeVisible) {
  525.       ObjectDelete(OFFTIME_NAME);
  526.       OffTimeVisible = false ;
  527.     }
  528.     return ;
  529.   }
  530.   if(!nextTicked) return ;
  531.  
  532.   datetime timStart = StringToTime(TimeStart);
  533.   datetime timEnd   = StringToTime(TimeEnd);
  534.  
  535.   MqlDateTime mqlTick, mqlStart, mqlEnd ;
  536.   TimeToStruct(TimeTick, mqlTick);
  537.   TimeToStruct(timStart, mqlStart);
  538.   TimeToStruct(timEnd, mqlEnd);
  539.  
  540.   // 活動時間帯のチェック
  541.   int ct = mqlTick.hour*60 + mqlTick.min ;
  542.   int st = mqlStart.hour*60 + mqlStart.min ;
  543.   int et = mqlEnd.hour*60 + mqlEnd.min ;
  544.   if(et<=st) {
  545.     if(st<=ct) et=24*60;
  546.     if(ct<=et) st=0;
  547.   }
  548.   bool activeTime = st <= ct && ct <= et ;
  549.  
  550.   bool isActivated = StartTime<TimeTick ;
  551.  
  552.   // 現在活動時間帯
  553.   if(activeTime) {
  554.     if(!isActivated)
  555.       StartTime = TimeTick ; // 現在時間を開始時間切り上げて完了
  556.     if(OffTimeVisible) {
  557.       ObjectDelete(OFFTIME_NAME);
  558.       OffTimeVisible = false ;
  559.     }
  560.     return ;
  561.   }
  562.  
  563.   // 活動時間を次の時間にセットする
  564.   MqlDateTime mqlNextStart = mqlTick ;
  565.   mqlNextStart.hour = mqlStart.hour ;
  566.   mqlNextStart.min = mqlStart.min ;
  567.   mqlNextStart.sec = 0 ;
  568.   datetime timNextStart = StructToTime(mqlNextStart) ;
  569.   while(timNextStart<TimeTick)  timNextStart += 24*60*60 ;
  570.   StartTime = timNextStart ;
  571.  
  572.   // 次の開始までの秒数
  573.   datetime timOff = StartTime - TimeTick ;
  574.   if(!OffTimeVisible) {
  575.     // OFF TIME テキストを表示
  576.     ObjectCreate(OFFTIME_NAME, OBJ_LABEL, 0, 0, 0);
  577.     ObjectSet(OFFTIME_NAME, OBJPROP_XDISTANCE, 10);
  578.     ObjectSet(OFFTIME_NAME, OBJPROP_YDISTANCE, 25);
  579.     ObjectSet(OFFTIME_NAME, OBJPROP_CORNER, 1);
  580.     ObjectSetString(0, OFFTIME_NAME, OBJPROP_TEXT, "OFF TIME");
  581.     ObjectSetString(0, OFFTIME_NAME, OBJPROP_FONT, "Verdana");
  582.     ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_FONTSIZE, 8);
  583.     ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_COLOR, ClrTimeControl);
  584.     OffTimeVisible = true ;
  585.   }
  586.  
  587.   int orderFlag = AlreadyOrdered(FLAG_SELL|FLAG_BUY,MAGICMA);
  588.  
  589.   switch(TimeAction) {
  590.     case TIMEACT_NONE:
  591.       // None
  592.       break;
  593.     case TIMEACT_FORCE_CLOSE_ALL:
  594.       // Force Close All positions
  595.       if(orderFlag!=0)
  596.         CheckoutOrderAll(orderFlag);
  597.       break;
  598.     case TIMEACT_FORCE_CLOSE_LONG:
  599.       // Force Close Long positions
  600.       if((orderFlag&FLAG_BUY)!=0)
  601.         CheckoutOrderAll(FLAG_BUY);
  602.       break;
  603.     case TIMEACT_FORCE_CLOSE_SHORT:
  604.       // Force Close Short positions
  605.       if((orderFlag&FLAG_SELL)!=0)
  606.         CheckoutOrderAll(FLAG_SELL);
  607.       break;
  608.     case TIMEACT_SOFT_CLOSE_ALL:
  609.       // Close All positions if profits are Positive
  610.       if(orderFlag!=0) {
  611.         STATUS status_long, status_short;
  612.         CheckStatus(OP_BUY,MAGICMA,status_long);
  613.         CheckStatus(OP_SELL,MAGICMA,status_short);
  614.         double total = status_long.GrossProfit+status_short.GrossProfit ;
  615.         if(total>0) {
  616.           CheckoutOrderAll(orderFlag);
  617.         }
  618.       }
  619.       break;
  620.     case TIMEACT_SOFT_CLOSE_LONG:
  621.       // Close Long positions if profits are Positive
  622.       if((orderFlag&FLAG_BUY)!=0) {
  623.         STATUS status_long;
  624.         CheckStatus(OP_BUY,MAGICMA,status_long);
  625.         double total=status_long.GrossProfit;
  626.         if(total>0) {
  627.           CheckoutOrderAll(FLAG_BUY);
  628.         }
  629.       }
  630.       break;
  631.     case TIMEACT_SOFT_CLOSE_SHORT:
  632.       // Close Short positions if profits are Positive
  633.       if((orderFlag&FLAG_SELL)!=0) {
  634.         STATUS status_short;
  635.         CheckStatus(OP_SELL,MAGICMA,status_short);
  636.         double total=status_short.GrossProfit;
  637.         if(total>0) {
  638.           CheckoutOrderAll(FLAG_SELL);
  639.         }
  640.       }
  641.       break;
  642.   }
  643. }
  644. //---------------------------------------------------------------------------
  645. //メインタイムを返す
  646. datetime MainTime(int shift=0)
  647. {
  648.   return iTime(Symbol(), MainTimeFrame, shift);
  649. }
  650. //---------------------------------------------------------------------------
  651. //メインPERIODを返す
  652. int MainPeriod()
  653. {
  654.   int period = MainTimeFrame ;
  655.   if(!period) period = Period();
  656.   return period ;
  657. }
  658. //---------------------------------------------------------------------------
  659. //タイムコントロールの基軸時間を返す
  660. datetime BaseTime()
  661. {
  662.   switch(TimeBase) {
  663.     case TIMEBASE_GMT:               // Greenwich Mean Time (GMT)
  664.       return TimeGMT();
  665.     case TIMEBASE_LOCAL:             // Local Time
  666.       return TimeLocal();
  667.     case TIMEBASE_SERVER:            // Server Time
  668.       return TimeCurrent();
  669.   }
  670.   return 0;
  671. }
  672. //---------------------------------------------------------------------------
  673. //金額表示の更新
  674. void UpdateAmount(double amount, int positions)
  675. {
  676.   if(ShowAmount) {
  677.     if(positions>0) {
  678.       string s = DoubleToAmount(amount,AmountDig) ;
  679.       if(amount>0) s = "+" + s ;
  680.       ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s);
  681.       if(amount<0)
  682.         ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_NEGA);
  683.       else
  684.         ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
  685.     }else {
  686.       string s = ObjectGetString(0, AMOUNT_NAME, OBJPROP_TEXT);
  687.       int ln=StringLen(s);
  688.       if(ln>0) {
  689.         if(s[ln-1]!='-')
  690.           ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s+"-");
  691.       }
  692.     }
  693.   }
  694. }
  695. //---------------------------------------------------------------------------
  696. //状態チェック
  697. //-----
  698. struct ORDER_STATUS {
  699.   int Ticket;
  700.   double Price;
  701.   double Stoploss;
  702.   double Takeprofit;
  703.   double Lots;
  704.   double Profit;
  705.   datetime OpenTime;
  706.   string Comment;
  707.   //-----
  708.   ORDER_STATUS() {
  709.     Ticket = -1 ;
  710.     Price = Stoploss = Takeprofit = Lots = Profit = 0.0 ;
  711.     OpenTime = 0 ;
  712.     Comment = "" ;
  713.   }
  714.   ORDER_STATUS(
  715.       int Ticket_,
  716.       double Price_,
  717.       double Stoploss_,
  718.       double Takeprofit_,
  719.       double Lots_,
  720.       double Profit_,
  721.       datetime OpenTime_,
  722.       string Comment_ ) {
  723.     Ticket = Ticket_;
  724.     Price = Price_;
  725.     Stoploss = Stoploss_;
  726.     Takeprofit = Takeprofit_;
  727.     Lots = Lots_;
  728.     Profit = Profit_;
  729.     OpenTime = OpenTime_;
  730.     Comment = Comment_;
  731.   }
  732.   bool operator <(const ORDER_STATUS &rhs) const {
  733.     return Price<rhs.Price;
  734.   }
  735. };
  736. //-----
  737. struct STATUS {
  738.   int Type, Magic;
  739.   int Positions, PyramidPositions, AveragePositions;
  740.   double MinPrice, MaxPrice, BorderPrice;
  741.   double MinPriceLots, MaxPriceLots;
  742.   double MinPriceProfit, MaxPriceProfit;
  743.   double MinPriceStoploss, MaxPriceStoploss;
  744.   int MinPriceTicket, MaxPriceTicket;
  745.   double MinStoploss, MaxStoploss;
  746.   double MinTakeprofit, MaxTakeprofit;
  747.   double MinLots, MaxLots;
  748.   datetime MinOpenTime, MaxOpenTime;
  749.   double PyramidMinLots, PyramidMaxLots;
  750.   double AverageMinLots, AverageMaxLots;
  751.   double TotalPrices, TotalLots;
  752.   double CurrentPrices, MedianPrices;
  753.   double GrossProfit;
  754.   double PositiveProfit;
  755.   CArrayObj *Orders;
  756.   STATUS() {
  757.     Orders = new CArrayObj();
  758.   }
  759.   ~STATUS() {
  760.     delete Orders;
  761.   }
  762.   void Check(int type, int magic) {
  763.     Type=type;
  764.     Magic=magic;
  765.     Positions = 0 ;
  766.     PyramidPositions = 0 ;
  767.     AveragePositions = 0 ;
  768.     MinPrice = DBL_MAX ;
  769.     MaxPrice = 0.0 ;
  770.     MinPriceLots = 0.0 ;
  771.     MaxPriceLots = 0.0 ;
  772.     MinPriceProfit = 0.0 ;
  773.     MaxPriceProfit = 0.0 ;
  774.     MinPriceStoploss = 0.0 ;
  775.     MaxPriceStoploss = 0.0 ;
  776.     MinPriceTicket = 0 ;
  777.     MaxPriceTicket = 0 ;
  778.     MinStoploss = DBL_MAX ;
  779.     MaxStoploss = 0.0 ;
  780.     MinTakeprofit = DBL_MAX ;
  781.     MaxTakeprofit = 0.0 ;
  782.     MinLots = DBL_MAX ;
  783.     MaxLots = 0.0 ;
  784.     MinOpenTime = TimeCurrent() ;
  785.     MaxOpenTime = 0 ;
  786.     PyramidMinLots = DBL_MAX ;
  787.     PyramidMaxLots = 0.0 ;
  788.     AverageMinLots = DBL_MAX ;
  789.     AverageMaxLots = 0.0 ;
  790.     BorderPrice = 0.0 ;
  791.     GrossProfit = 0.0 ;
  792.     PositiveProfit = 0.0 ;
  793.     CurrentPrices = 0.0 ;
  794.     MedianPrices = 0.0 ;
  795.     Orders.Clear();
  796.     double halfSpread = (Ask-Bid)/2.0;
  797.     double totalPrice=0, totalLots=0 ;
  798.     for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
  799.       if( OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol() ) {
  800.         if(magic==OrderMagicNumber()) {
  801.           if(type==OrderType()) {
  802.             int orderTicket = OrderTicket() ;
  803.             double orderPrice = OrderOpenPrice();
  804.             double orderStoploss = OrderStopLoss();
  805.             double orderTakeprofit = OrderTakeProfit();
  806.             double orderLots = OrderLots();
  807.             double orderProfit = OrderProfit() ;
  808.             datetime orderOpenTime = OrderOpenTime() ;
  809.             string orderComment = OrderComment();
  810.             AddToArray(Orders, ORDER_STATUS(
  811.               orderTicket,
  812.               orderPrice,
  813.               orderStoploss,
  814.               orderTakeprofit,
  815.               orderLots,
  816.               orderProfit,
  817.               orderOpenTime,
  818.               orderComment )
  819.             );
  820.             GrossProfit += orderProfit;
  821.             if(orderProfit>0.0)
  822.               PositiveProfit += orderProfit;
  823.             if(orderPrice<MinPrice) {
  824.               MinPrice = orderPrice ;
  825.               MinPriceLots = orderLots ;
  826.               MinPriceProfit = orderProfit ;
  827.               MinPriceStoploss = orderStoploss ;
  828.               MinPriceTicket = orderTicket ;
  829.             }
  830.             if(orderPrice>MaxPrice) {
  831.               MaxPrice = orderPrice ;
  832.               MaxPriceLots = orderLots ;
  833.               MaxPriceProfit = orderProfit ;
  834.               MaxPriceStoploss = orderStoploss ;
  835.               MaxPriceTicket = orderTicket ;
  836.             }
  837.             if(orderStoploss<MinStoploss) MinStoploss = orderStoploss;
  838.             if(orderStoploss>MaxStoploss) MaxStoploss = orderStoploss;
  839.             if(orderTakeprofit<MinTakeprofit) MinTakeprofit = orderTakeprofit;
  840.             if(orderTakeprofit>MaxTakeprofit) MaxTakeprofit = orderTakeprofit;
  841.             if(orderLots<MinLots) MinLots = orderLots;
  842.             if(orderLots>MaxLots) MaxLots = orderLots;
  843.             totalPrice += orderPrice*orderLots ;
  844.             totalLots += orderLots;
  845.             if(type==OP_BUY) {
  846.               CurrentPrices += (Bid - orderPrice) * orderLots ;
  847.               MedianPrices += (orderPrice + halfSpread) * orderLots ;
  848.             }
  849.             else if(type==OP_SELL) {
  850.               CurrentPrices += (orderPrice - Ask) * orderLots ;
  851.               MedianPrices += (orderPrice - halfSpread) * orderLots ;
  852.             }
  853.             if(MaxOpenTime<orderOpenTime) MaxOpenTime=orderOpenTime;
  854.             if(MinOpenTime>orderOpenTime) MinOpenTime=orderOpenTime;
  855.             if(StringFind(orderComment,"PRMD")>=0) {
  856.               if(orderLots>PyramidMaxLots)
  857.                 PyramidMaxLots = orderLots ;
  858.               if(orderLots<PyramidMinLots)
  859.                 PyramidMinLots = orderLots ;
  860.               PyramidPositions++;
  861.             }
  862.             if(StringFind(orderComment,"AVRG")>=0) {
  863.               if(orderLots>AverageMaxLots)
  864.                 AverageMaxLots = orderLots ;
  865.               if(orderLots<AverageMinLots)
  866.                 AverageMinLots = orderLots ;
  867.               AveragePositions++;
  868.             }
  869.             Positions++;
  870.           }
  871.         }
  872.       }
  873.     }
  874.     Orders.Sort(ARRAY_SORT_ASCEND);
  875.     if(!PyramidPositions) {
  876.       PyramidMinLots = Lots ;
  877.       PyramidMaxLots = Lots ;
  878.     }
  879.     if(!AveragePositions) {
  880.       AverageMinLots = Lots ;
  881.       AverageMaxLots = Lots ;
  882.     }
  883.     if(totalLots>0) {
  884.       BorderPrice = totalPrice / totalLots ;
  885.     }
  886.     TotalPrices = totalPrice ;
  887.     TotalLots = totalLots ;
  888.   }
  889.   /*
  890.   double ProfitPrice(double borderPrice=0.0) const {
  891.     if(borderPrice==0.0) borderPrice = BorderPrice;
  892.     if(borderPrice>0.0) {
  893.       //double stride = PyramidingStride * Point ;
  894.       switch(Type) {
  895.         case OP_BUY: {
  896.           double bar = MathMax(MaxPrice,BuyMaxPrice)-borderPrice ;
  897.           if(bar>0.0) {
  898.             return bar * (ProfitRatePer / 100.0) + borderPrice ;
  899.           }
  900.           break;
  901.         }
  902.         case OP_SELL: {
  903.           double bar = MathMin(MinPrice,SellMinPrice)-borderPrice ;
  904.           if(bar<0.0) {
  905.             return bar * (ProfitRatePer / 100.0) + borderPrice ;
  906.           }
  907.           break;
  908.         }
  909.       }
  910.     }
  911.     return borderPrice ;
  912.   }
  913.   */
  914.   double MedianBorderPrice(const STATUS &revStatus, double lossPrices=0.0) const
  915.   {
  916.     double medianLots = Type==OP_BUY ? TotalLots : -TotalLots ;
  917.     medianLots += revStatus.Type==OP_BUY ? revStatus.TotalLots: -revStatus.TotalLots ;
  918.     if(Type==OP_BUY?medianLots>0.0:medianLots<0.0) {
  919.       double medianPrices = Type==OP_BUY ? MedianPrices-lossPrices : -MedianPrices+lossPrices ;
  920.       medianPrices += revStatus.Type==OP_BUY ? revStatus.MedianPrices: -revStatus.MedianPrices ;
  921.       double medianBorder = medianPrices/medianLots ;
  922.       switch(Type) {
  923.         case OP_BUY:
  924.             medianBorder -= (Ask-Bid)/2.0;
  925.             break;
  926.         case OP_SELL:
  927.             medianBorder += (Ask-Bid)/2.0;
  928.             break;
  929.       }
  930.       return medianBorder ;
  931.     }
  932.     return 0.0;
  933.   }
  934. };
  935. //-----
  936. int CheckStatus(int type, int magic, STATUS &status)
  937. {
  938.   status.Check(type,magic);
  939.   return status.Positions;
  940. }
  941. //---------------------------------------------------------------------------
  942. //MARK:動作チェック
  943. void CheckBehavior(bool nextTimed)
  944. {
  945.   // 複利ロット計算
  946.   if(Compounding) {
  947.     double balance = AccountBalance();
  948.     if(BalanceIncludeCredit) balance += AccountCredit();
  949.     Lots = balance*BaseLots/CompoundingBase ;
  950.     if(Lots<MinLots) Lots = MinLots ;
  951.     if(Lots>MaxLots) Lots = MaxLots ;
  952.   }
  953.  
  954.   // 全体のステータスを取得
  955.   STATUS BuyWholeStatus, SellWholeStatus ;
  956.   CheckStatus(OP_BUY, MAGICMA, BuyWholeStatus);
  957.   CheckStatus(OP_SELL, MAGICMA, SellWholeStatus);
  958.  
  959.   // 金額を更新
  960.   double CurAmount = BuyWholeStatus.GrossProfit+SellWholeStatus.GrossProfit ;
  961.   int CurPositions = BuyWholeStatus.Positions+SellWholeStatus.Positions ;
  962.   UpdateAmount(CurAmount,CurPositions);
  963.  
  964.   // 自動処理
  965.   if(Automation) {
  966.  
  967.     // 最大損益のチェック
  968.     if(CurAmount<0) {
  969.       double balance = AccountBalance();
  970.       if(BalanceIncludeCredit) balance += AccountCredit();
  971.       if(balance*MaxGrosslossPer/100.0<-CurAmount) {
  972.         //最大損益を超えた場合は、すべて決済する
  973.         CheckoutOrderAll(FLAG_BUY|FLAG_SELL);
  974.         PrintMessage("Check-out orders by over Maximum Gross Loss");
  975.         return;
  976.       }
  977.     }
  978.  
  979.     // オーダーの処理
  980.     ProcessOrders(nextTimed, OP_BUY, BuyWholeStatus, SellWholeStatus);
  981.     ProcessOrders(nextTimed, OP_SELL, SellWholeStatus, BuyWholeStatus);
  982.  
  983.   }
  984.  
  985.   FlushTL=false;
  986. }
  987. //---------------------------------------------------------------------------
  988. //MARK:オーダーの処理
  989. void ProcessOrders(bool nextTimed, int orderType, const STATUS &status, const STATUS &revStatus)
  990. {
  991.   if(status.Positions<=0) return ;
  992.   color orderColor = orderType==OP_BUY ? ClrLongArrow : ClrShortArrow ;
  993.  
  994.   // トレーリング
  995.   if(Trailing) {
  996.     double tstart = TrailingStart*Point ;
  997.     double tstop = TrailingStop*Point ;
  998.     double minPadding = tstart+tstop ;
  999.     for(int i=status.Positions-1;i>=0;i--) {
  1000.       CSortable<ORDER_STATUS>* order =
  1001.         (CSortable<ORDER_STATUS>*)status.Orders.At(
  1002.           orderType==OP_SELL?i:status.Positions-1-i) ;
  1003.       if( orderType==OP_BUY ?
  1004.             order.key.Price>Bid-minPadding : order.key.Price<Ask+minPadding )
  1005.         break;
  1006.       double sl=0.0 ;
  1007.       if(  order.key.Stoploss==0.0 ||
  1008.            ( orderType==OP_BUY ?
  1009.              order.key.Stoploss<order.key.Price : order.key.Stoploss>order.key.Price) ) {
  1010.         //初回トレール
  1011.         sl = orderType==OP_BUY ? order.key.Price+tstart : order.key.Price-tstart ;
  1012.       }else {
  1013.         //既にトレール済
  1014.         sl = order.key.Stoploss ;
  1015.       }
  1016.       while( ( orderType==OP_BUY ? Bid-sl : sl-Ask ) >= tstop*2 ) {
  1017.         //カクカクにトレール幅を狭めていく
  1018.         sl += orderType==OP_BUY ? +tstop : -tstop ;
  1019.       }
  1020.       if(!InnerPoint(sl,order.key.Stoploss)) {
  1021.         //ストップロスを更新
  1022.         if(OrderModify(order.key.Ticket,order.key.Price,sl,order.key.Takeprofit,0,orderColor)) {
  1023.           order.key.Stoploss = sl ;
  1024.         }else PrintLastError();
  1025.       }
  1026.     }
  1027.   }
  1028.  
  1029.   // 3EMA処理
  1030.   if(MA3 && (nextTimed||FlushTL)) {
  1031.     double HalfSpread = (Ask-Bid)/2.0;
  1032.     double FastMA0 = iMA(NULL, MainTimeFrame, MA3FastPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  1033.     double MediumMA0 = iMA(NULL, MainTimeFrame, MA3MediumPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  1034.     double SlowMA0 = iMA(NULL, MainTimeFrame, MA3SlowPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  1035.     for(int i=status.Positions-1;i>=0;i--) {
  1036.       CSortable<ORDER_STATUS>* order =
  1037.         (CSortable<ORDER_STATUS>*)status.Orders.At(
  1038.           orderType==OP_SELL?i:status.Positions-1-i) ;
  1039.       double price = order.key.Price ;
  1040.       double sl = order.key.Stoploss ;
  1041.       double trail_sl=0.0;
  1042.       double checkout_denom=0.0;
  1043.       string checkout_reason="";
  1044.       if(InnerPoint(sl,price)) { // プライスがslに一致
  1045.         if(FlushTL&&!nextTimed) continue;
  1046.         if(!InnerPoint(MediumMA0,price) &&
  1047.           (orderType==OP_BUY?MediumMA0-HalfSpread>price:MediumMA0+HalfSpread<price)) { // Medium MA がプライス以上
  1048.           if(orderType==OP_BUY?FastMA0>Ask:FastMA0<Bid) { // Fast MA が現価以上
  1049.             // 決済設定
  1050.             checkout_denom = LotsDenomMAFast ;
  1051.             checkout_reason = "Check-out by Fast MA" ;
  1052.             if(orderType==OP_BUY?MediumMA0>Ask:MediumMA0<Bid) // Medium MA が現価より上
  1053.             { checkout_reason += " & Medium MA"; checkout_denom = 1.0 ;} // 全決済する
  1054.             // ストップロスを Medium MA 値に更新する
  1055.             trail_sl = MediumMA0 + (orderType==OP_BUY?-HalfSpread:+HalfSpread) ;
  1056.           }
  1057.         }
  1058.       }else if(sl!=0.0&&(orderType==OP_BUY?sl>price:sl<price)) { //プライスがslより下
  1059.         if(FlushTL&&!nextTimed) continue;
  1060.         if(orderType==OP_BUY?Ask<=MediumMA0:Bid>=MediumMA0) { //現価が Medium MA より下になった
  1061.           // 決済設定
  1062.           checkout_denom = 1.0 ; // 全決済
  1063.           checkout_reason = "Check-out by Medium MA" ;
  1064.         }
  1065.       }else { //プライスがslより上、もしくは、slが設定されていない
  1066.         if(FlushTL||MA3TLPeriod>0) { // TL(TimeLimited) ポジションが有効
  1067.           //ロウソク足の期間を計測
  1068.           datetime tperiod = MainPeriod() * 60 ;
  1069.           int period = int((CurTime-order.key.OpenTime)/tperiod);
  1070.           if(FlushTL||period>=MA3TLPeriod-1) { //TL(TimeLimited)期間が過ぎている
  1071.             if(orderType==OP_BUY?Bid>price:Ask<price) { // 利確できる位置にある
  1072.               if(!FlushTL&&(orderType==OP_BUY?FastMA0>Ask||MediumMA0>Ask:FastMA0<Bid||MediumMA0<Bid)) { // 2MA が現価より上
  1073.                 // 現価が 2MA を抜かすまでの間、ストップロスを原価ギリギリまで引き上げておく
  1074.                 trail_sl = price + (orderType==OP_BUY?-Point:+Point);
  1075.               }else { // FastMA が現価以下
  1076.                 // 決済設定
  1077.                 checkout_denom = LotsDenomTL ;
  1078.                 checkout_reason = "Check-out by TL(TimeLimited)" ;
  1079.                 // ストップロスを原価に引き上げる
  1080.                 trail_sl = price ;
  1081.               }
  1082.             }
  1083.           }
  1084.         }
  1085.         if(!FlushTL||nextTimed) {
  1086.           if(sl==0.0) { //ストップロスが設定されていない
  1087.             if(MaxGrosslossPer>=100.0) { // Max Gross loss が 100%以上
  1088.               if(orderType==OP_BUY?Ask<=SlowMA0:Bid>=SlowMA0) { //現価が Slow MA より下になった
  1089.                 // 損切設定
  1090.                 checkout_denom = 1.0 ; // 全決済
  1091.                 checkout_reason = "Loss-cut order by Slow MA" ;
  1092.               }
  1093.             }
  1094.           }
  1095.         }
  1096.       }
  1097.       if(trail_sl!=0.0) {
  1098.         //MAによるトレーリング
  1099.         if(sl==0.0||(!InnerPoint(sl,trail_sl)&&(orderType==OP_BUY?sl<trail_sl:sl>trail_sl))) {
  1100.           sl = trail_sl ;
  1101.           if(OrderModify(order.key.Ticket,order.key.Price,sl,order.key.Takeprofit,0,orderColor)) {
  1102.             order.key.Stoploss = sl ;
  1103.           }else PrintLastError();
  1104.         }
  1105.       }
  1106.       if(checkout_denom>0.0) {
  1107.         //MAによる決済処理
  1108.         double lots = AdjLots(order.key.Lots/checkout_denom) ;
  1109.         if(lots<MinLots) lots = MinLots ;
  1110.         if(lots>order.key.Lots) lots = order.key.Lots ;
  1111.         if(CheckoutOrder(orderType,order.key.Ticket,lots)) {
  1112.           PrintMessage(checkout_reason);
  1113.           order.key.Lots -= lots ;
  1114.         }
  1115.       }
  1116.     }
  1117.   }
  1118. }
  1119. //---------------------------------------------------------------------------
  1120. //すでに注文済みかどうか
  1121. int AlreadyOrdered(int orderFlag, int magic)
  1122. {
  1123.   int flag = 0 ;
  1124.   for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
  1125.     if( OrderSelect(i, SELECT_BY_POS) ) {
  1126.       int orderMagic = OrderMagicNumber() ;
  1127.       if( OrderSymbol() == Symbol() && magic==orderMagic ){
  1128.         if( OrderType() == OP_BUY && (orderFlag&FLAG_BUY)!=0 ){
  1129.           flag |= FLAG_BUY  ; if(flag==orderFlag) break;
  1130.         }else if( OrderType() == OP_SELL && (orderFlag&FLAG_SELL)!=0 ){
  1131.           flag |= FLAG_SELL ; if(flag==orderFlag) break;
  1132.         }
  1133.       }
  1134.     }
  1135.   }
  1136.   return flag;
  1137. }
  1138. //---------------------------------------------------------------------------
  1139. //マニュアルポジション発注
  1140. int EntryManualPosition(string detector, int entryType, double lots)
  1141. {
  1142.   double sl=0.0, tp=0.0;
  1143.   switch(entryType)  {
  1144.     case OP_BUY:
  1145.       if(Stoploss!=0.0) sl = Ask-Stoploss*Point ;
  1146.       if(Takeprofit!=0.0) tp = Ask+Takeprofit*Point ;
  1147.       break;
  1148.     case OP_SELL:
  1149.       if(Stoploss!=0.0) sl = Bid+Stoploss*Point ;
  1150.       if(Takeprofit!=0.0) tp = Bid-Takeprofit*Point ;
  1151.       break;
  1152.   }
  1153.   if(sl==0.0) {
  1154.     if(MaxGrosslossPer>=100.0) {
  1155.       // SlowMAの現在位置がAsk/Bidよりも上回っていないことを確認する
  1156.       double HalfSpread = (Ask-Bid)/2.0;
  1157.       double SlowMA0 = iMA(NULL, MainTimeFrame, MA3SlowPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  1158.       if(entryType==OP_BUY?SlowMA0>=Ask:SlowMA0<=Bid) {
  1159.         PrintMessage("Entrying failed due to Slow MA over price reached");
  1160.         return -1 ; // invalid
  1161.       }
  1162.     }
  1163.   }
  1164.   return MakeOrder(entryType,lots,sl,tp,detector,MAGICMA);
  1165. }
  1166. //---------------------------------------------------------------------------
  1167. //注文の発注
  1168. int MakeOrder(int entryType, double lots, double sl, double tp, string detector, int magic,
  1169.   double entryPrice=0.0, datetime expiration=0)
  1170. {
  1171.   string entryName = ENTRY_NAME"("+detector+")" ;
  1172.  
  1173.   for(int retry=0; retry<ORDER_RETRY; retry++) {
  1174.  
  1175.     color orderColor = clrNONE;
  1176.  
  1177.     if( (entryType==OP_BUY||entryType==OP_SELL) &&
  1178.       MarketInfo(NULL,MODE_SPREAD) > Spread) { Sleep(2000); continue ; }
  1179.  
  1180.     double price=entryPrice ;
  1181.     switch(entryType) {
  1182.     case OP_BUY: case OP_BUYSTOP: case OP_BUYLIMIT:
  1183.       if(price==0.0) price = Ask ;
  1184.       orderColor = ClrLongArrow ;
  1185.       break;
  1186.     case OP_SELL: case OP_SELLSTOP: case OP_SELLLIMIT:
  1187.       if(price==0.0) price = Bid ;
  1188.       orderColor = ClrShortArrow ;
  1189.       break;
  1190.     }
  1191.  
  1192.     int ticket=MakeOrderSub(
  1193.       entryType,price,lots,sl,tp,entryName,
  1194.         magic,expiration,orderColor);
  1195.     if(ticket>=0)
  1196.       return ticket ;
  1197.  
  1198.     Sleep(2000);
  1199.   }
  1200.  
  1201.   return -1;
  1202. }
  1203. //---------------------------------------------------------------------------
  1204. //注文発注サブルーチン
  1205. int MakeOrderSub(int entryType, double entryPrice, double lots, double sl=0.0, double tp=0.0,
  1206.   string comment=NULL, int magicNumber=0, datetime expiration=0, color orderColor=clrNONE)
  1207. {
  1208.    int res = OrderSend(
  1209.                       NULL,
  1210.                       entryType,
  1211.                       lots,
  1212.                       entryPrice,
  1213.                       Slippage,
  1214.                       sl,
  1215.                       tp,
  1216.                       comment,
  1217.                       magicNumber,
  1218.                       expiration,
  1219.                       orderColor
  1220.                    );
  1221.    if(res<0)
  1222.      PrintLastError();
  1223.    return res;
  1224. }
  1225. //---------------------------------------------------------------------------
  1226. //注文の決済
  1227. bool CheckoutOrder( int orderType, int orderTicket, double orderLots)
  1228. {
  1229.   for(int retry=0; retry<ORDER_RETRY; retry++) {
  1230.     double checkoutPrice = 0.0 ;
  1231.     color orderColor = clrNONE ;
  1232.     switch(orderType) {
  1233.     case OP_BUY:
  1234.       checkoutPrice = Bid ;
  1235.       orderColor = ClrLongArrow ;
  1236.       break;
  1237.     case OP_SELL:
  1238.       checkoutPrice = Ask ;
  1239.       orderColor = ClrShortArrow ;
  1240.       break;
  1241.     }
  1242.     if(OrderClose(orderTicket, orderLots, checkoutPrice, Slippage, orderColor))
  1243.       return true;
  1244.     Sleep(100);
  1245.   }
  1246.   PrintLastError();
  1247.   return false ;
  1248. }
  1249. //---------------------------------------------------------------------------
  1250.  
  1251.   struct OBJECT_CHECKOUT {
  1252.     int Ticket;
  1253.     double Profit;
  1254.     OBJECT_CHECKOUT() {
  1255.       Ticket = -1 ;
  1256.       Profit = 0.0 ;
  1257.     }
  1258.     OBJECT_CHECKOUT(int Ticket_, double Profit_) {
  1259.       Ticket = Ticket_ ;
  1260.       Profit = Profit_ ;
  1261.     }
  1262.     bool operator <(const OBJECT_CHECKOUT &rhs) const {
  1263.       return Profit < rhs.Profit ;
  1264.     }
  1265.   };
  1266.  
  1267. //注文の全決済
  1268. bool CheckoutOrderAll(int orderFlag, double lotsDenom=1.0)
  1269. {
  1270.   bool result = true ;
  1271.   CArrayObj *array = new CArrayObj();
  1272.   for(int i = 0 ; i < OrdersTotal() ; i++){
  1273.     if(OrderSelect(i, SELECT_BY_POS)) {
  1274.       int magic = OrderMagicNumber();
  1275.       int orderType = OrderType() ;
  1276.       if( (orderType==OP_BUY&&(orderFlag&FLAG_BUY)!=0) ||
  1277.           (orderType==OP_SELL&&(orderFlag&FLAG_SELL)!=0) ) {
  1278.         if( OrderSymbol() == Symbol() && magic == MAGICMA ){
  1279.           AddToArray(array,OBJECT_CHECKOUT(OrderTicket(),OrderProfit()));
  1280.         }
  1281.       }
  1282.     }
  1283.   }
  1284.   array.Sort(ARRAY_SORT_DESCEND); // 利益が多い順に並べ替える
  1285.   for(int i=0;i<array.Total();i++) {
  1286.     CSortable<OBJECT_CHECKOUT> *node = (CSortable<OBJECT_CHECKOUT>*)array.At(i);
  1287.     if(OrderSelect(node.key.Ticket, SELECT_BY_TICKET)) {
  1288.       if(!CheckoutOrder(OrderType(),OrderTicket(),OrderLots()/lotsDenom)) {
  1289.         result = false ; break;
  1290.       }
  1291.     }
  1292.   }
  1293.   delete array ;
  1294.   return result ;
  1295. }
  1296. //---------------------------------------------------------------------------
  1297. //000,000,000表示
  1298. // http://chocottokozukai.seesaa.net/article/417824756.html
  1299. string DoubleToAmount(double inputdata, int dig)
  1300. {
  1301.   string returnstr = DoubleToStr(inputdata,dig);
  1302.   int length;
  1303.   int noofcomma;
  1304.   int firstcomma;
  1305.  
  1306.   length = StringLen(DoubleToStr(MathFloor(inputdata),0));
  1307.   if (inputdata >= 0) noofcomma = (int)MathFloor((length - 1) / 3);
  1308.   else noofcomma = (int)MathFloor((length - 2) / 3);
  1309.   if (noofcomma == 0) return (returnstr);
  1310.  
  1311.   firstcomma = length - noofcomma * 3;
  1312.   if (firstcomma == 0) firstcomma = 3;
  1313.  
  1314.   for (int i = 0; i < noofcomma; i++){
  1315.     returnstr = StringConcatenate(StringSubstr(returnstr, 0, firstcomma + i * 4),
  1316.       ",",StringSubstr(returnstr, firstcomma + i * 4));
  1317.   }
  1318.  
  1319.   return (returnstr);
  1320. }
  1321. //---------------------------------------------------------------------------
  1322. /* ( おまけ )
  1323. //---------------------------------------------------------------------------
  1324. // ZIGZAG_STATUS
  1325. //-----
  1326. struct ZIGZAG_STATUS {
  1327.   double Price;
  1328.   datetime Time;
  1329.   int Shift;
  1330.   ZIGZAG_STATUS() {Price=0;Time=0;Shift=0;}
  1331.   ZIGZAG_STATUS(double Price_, datetime Time_, int Shift_) {
  1332.     Price = Price_ ;
  1333.     Time = Time_ ;
  1334.     Shift = Shift_ ;
  1335.   }
  1336.   bool operator <(const ZIGZAG_STATUS &rhs) const {
  1337.     return Time < rhs.Time ;
  1338.   }
  1339. };
  1340. //-----
  1341. // ZigZag のポジションを列挙する
  1342. bool EnumZigZagStatus(int num, ZIGZAG_STATUS &arrayZZ[], int si=0, int expire=INT_MAX)
  1343. {
  1344.   int limit = expire == INT_MAX ? INT_MAX : si + expire ;
  1345.   limit = MathMin(limit,iBars(NULL,MainTimeFrame)-1);
  1346.   ArraySetAsSeries(arrayZZ,true);
  1347.   ArrayResize(arrayZZ,num);
  1348.   for (int i = si, n=0; i < limit ; i++) {
  1349.     double zz = iCustom(NULL, MainTimeFrame, "ZigZag", ZigZagDepth, ZigZagDeviation, ZigZagBackstep, 0, i);
  1350.     if(zz!=0) {
  1351.       arrayZZ[n] = ZIGZAG_STATUS(zz, MainTime(i), i);
  1352.       n++;
  1353.       if(n>=num)
  1354.         return true;
  1355.     }
  1356.   }
  1357.   return false;
  1358. }
  1359. //---------------------------------------------------------------------------
  1360. // XMA+ZigZag の最初のエントリポイントが存在するかどうか調べる
  1361. int CheckDetectorXMAZigZag(double &entryPrice, double &stoploss, int si=0)
  1362. {
  1363.   ZIGZAG_STATUS zz[];
  1364.   bool valid = EnumZigZagStatus(3,zz,si,ExpirationPeriod*3);
  1365.   if(valid&&zz[0].Shift<ZigZagBackstep)
  1366.     valid = EnumZigZagStatus(3,zz,zz[0].Shift+1,ExpirationPeriod*3);
  1367.   (以下略・・・)
  1368. }
  1369. //---------------------------------------------------------------------------
  1370. */
  1371.  
Tags: Mt4
Advertisement
Add Comment
Please, Sign In to add comment