HYROLEAN

test_3ma_user_v2.mq4

Apr 6th, 2026 (edited)
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 39.52 KB | Money | 0 0
  1. // test_3ma_user_v2.mq4
  2. //   by 2024-2026 (c)hyrolean
  3. //---------------------------------------------------------------------------
  4. #property copyright "2024-2026, (c)hyrolean"
  5. #property link      "https://pastebin.com/rAPtby8g"
  6. #property version   "2.00"
  7. #property strict
  8.  
  9. #include <stdlib.mqh>
  10. #include <User/hyrDefs.mqh>    // https://pastebin.com/iHZKAWqC
  11. #include <User/hyrTmpl.mqh>    // https://pastebin.com/LG1vurny
  12. #include <User/hyrGlobal.mqh>  // https://pastebin.com/2PdBW6NQ
  13. #include <User/hyrStatus.mqh>  // https://pastebin.com/D9JP5Ujq
  14.  
  15.   // version 2.00
  16.   //  - ユーザーロット調整機能を追加
  17.   //  - 約定が失敗した際に音とエラーメッセージで知らせる処理を追加
  18.   //  - 主要関数を自作ライブラリに置換えてコンパクト化
  19.  
  20. /*
  21.  
  22.  3EMA 手法 ( 状態遷移情報をターミナルに格納する変数を必要としないバージョン )
  23.  
  24.  ・ 建玉するときに、EMA50をストップロスに設定する(Stoploss=0の場合)
  25.  
  26.     ※ 現在価格がEMA50を下回るところでは、建玉を行わないようにする
  27.  
  28.  ・ ストップロスが玉の価格より下にあるものに的を絞り、EMA50を基準にトレーリングを行う
  29.  
  30.     ※ ただし、玉の価格がEMA50より下にある場合は、上記の操作を見送ることとする
  31.  
  32.  ・ ストップロスが玉の価格より下にあるものに的を絞り、ロウソク足が5期間経過後から、
  33.    現在のプライスが超えた時点でストップロスをエントリープライスに移動し、ロットの1/3を利確する
  34.  
  35.    ロウソク足の期間の出し方:
  36.      iBarShift(_Symbol, MainTimeFrame, <建玉時刻>)>=5
  37.  
  38.     ※ 5期間経過後に未だ現価が下にある場合は、現価が上に来るまでこの試行は継続
  39.       されることとし、現価がロウソク足1期間でも抜けたら即ストップロスをエントリープライスに移動
  40.       し、ロットの1/3利確することとする
  41.  
  42.  ・ 現在価格がEMA10を下回った場合、ストップロスがエントリープライスに一致する玉を検出し、
  43.    EMA20の位置にストップロスを移動し、ロットの1/2を利確する(この時点でEMA20も現在価格
  44.    を突破している場合は、全ロットを利確することとする)
  45.  
  46.     ※ ただし、玉の価格がEMA20より上にある場合は、上記の操作を見送ることとする
  47.  
  48.  ・ ストップロスが玉の価格より上にあるものに的を絞り、EMA20を基準にトレーリングを行う
  49.  
  50. */
  51.  
  52. /*
  53.  
  54.   使い方::
  55.  
  56.   左上の|SELL|BUY|ボタンを選んでポジションを自分で打ちます。
  57.   ポジションを打ったら、sl(ストップロス)のBARを自分の好みの場所に移動させます。
  58.   以降、3EMAの手法に従って自動的に利確されます。(逆行しなければですが…)
  59.   運悪く逆行してしまった場合は、損益の㌫、または、slに応じて自動損切されます。
  60.  
  61.   エントリーのコツとしては、上から現在価格,EMA10,EMA20,EMA50の順番で並んでいるときは、
  62.   ロング(買い)、逆に、上からEMA50,EMA20,EMA10,現在価格の順番で並んでいるときは、
  63.   ショート(売り)でエントリーすると上手くいくかもしれないです。
  64.  
  65.   (利確のタイミングを図りたい場合など、自動処理を一時的に中断したい場合は、Automate
  66.   Processing Orders をfalseに設定すると無効に出来ます。)
  67.  
  68.   MT4を閉じてもslとエントリープライスの位置だけで状態を把握する為、万が一VPS等が停止し
  69.   てしまってもサーバー側に建玉の情報さえ残っていればMT4を再度立ち上げてこのEAを有
  70.   効化するだけで状態復帰可能な仕様に仕上げています。
  71.  
  72.   以上ゞ
  73.  
  74. */
  75.  
  76. #define ENTRY_NAME "3MAUserV2"
  77. #define ORDER_RETRY 10
  78. #define ORDER_RETRY_SLEEP 100
  79. #define ORDER_RETRY_DURATION 1000
  80.  
  81. enum ENUM_POSI {
  82.   POSI_STOP,                  // Stop
  83.   POSI_ONLY_LONG,             // Only Long
  84.   POSI_ONLY_SHORT,            // Only Short
  85.   POSI_HALF_LONG_AND_SHORT,   // Long & Short (Half duplex)
  86.   POSI_FULL_LONG_AND_SHORT    // Long & Short (Full duplex)
  87. };
  88.  
  89. #define STATAG_CHECKEDOUT 1
  90.  
  91. input bool      Automation      = true;     // Automate processing orders
  92. input ENUM_TIMEFRAMES MainTimeFrame = PERIOD_CURRENT; // Main Time Frame
  93. input MAGIC MAGICMA             = 0;        // Magic Number
  94. input bool      TimeControl     = false;    // Time Control
  95. input ENUM_TIMEBASE TimeBase    = TIMEBASE_LOCAL; // Time Base
  96. input string    TimeStart       = "09:00";  // Time Start
  97. input string    TimeEnd         = "15:00";  // Time End
  98. input ENUM_TIMEACT TimeAction   = TIMEACT_NONE; // Time Action when time end reached
  99. input ENUM_MA_METHOD      MAMode= MODE_EMA; // MA mode
  100. input ENUM_APPLIED_PRICE  MAPriceType = PRICE_CLOSE; // MA price type
  101. input bool      MA3             = true;     // 3MA Enabled
  102. input int       MA3FastPeriod   = 10;       // 3MA Fast period
  103. input int       MA3MediumPeriod = 20;       // 3MA Medium period
  104. input int       MA3SlowPeriod   = 50;       // 3MA Slow period
  105. input int       MA3TLPeriod     = 5;        // 3MA TL(TimeLimited) period
  106. input int       Slippage        = 10;       // Max Slippage
  107. input int       Spread          = 50;       // Max Spread in points
  108. input double    BaseLots        = 0.1;      // Base Lots
  109. input double    StepLots        = 0.01;     // Step Lots
  110. input double    MinLots         = 0.01;     // Minimum Lots
  111. input double    MaxLots         = 50.0;     // Maximum Lots
  112. input double    LotsDenomTL     = 3.0;      // Lots denom of 3MA TL(TimeLimited)
  113. input double    LotsDenomMAFast = 2.0;      // Lots denom of 3MA Fast MA
  114. input double    Takeprofit      = 0;        // Take profit in points (0 = unlimited)
  115. input double    Stoploss        = 200;      // Stop loss in points (0 = Grossloss per or SlowMA trail)
  116. input double    MaxGrosslossPer = 25;       // Maximum Allowed Gross loss of Balance in percentage
  117. input bool      Compounding     = false;    // Compounding interest Enabled
  118. input double    CompoundingBase = 100000;   // Compounding Base Balance (Lots=BaseLots*Balance/BaseBalance)
  119. input bool      BalanceIncludeCredit= true; // Balance include Credit
  120. input bool      Trailing        = false;    // Trailing Enabled
  121. input double    TrailingStart   = 300;      // Trailing Start in points
  122. input double    TrailingStop    = 200;      // Trailing Stop in points
  123. input bool      ShowUserEntry   = true;     // Show user entry SELL/BUY buttons
  124. input bool      ShowCloseAll    = true;     // Show a CLOSE ALL button
  125. input bool      ShowCloseLong   = false;    // Show a CLOSE LONG button
  126. input bool      ShowCloseShort  = false;    // Show a CLOSE SHORT button
  127. input bool      ShowFlushTL     = true;     // Show a FLUSH TL button
  128. input bool      ShowAmount      = true;     // Show Current Amount
  129. input int       AmountDig       = 0;        // Amount Number of decimal places
  130. input color     ClrAmountPosi   = clrLightGoldenrod; // Amount Positive color
  131. input color     ClrAmountNega   = clrLightPink; // Amount Negative color
  132. input color     ClrTimeControl  = clrYellow; // Time Control Status color
  133. input color     ClrLongArrow    = clrBlue;  // Long Arrow color
  134. input color     ClrShortArrow   = clrRed;   // Short Arrow color
  135. input bool      DBGMODE         = true;     // DEBUG MODE
  136.  
  137. //===========================================================================
  138. // 型
  139. //---------------------------------------------------------------------------
  140. // OBJECT_PARTCLOSED
  141. struct OBJECT_PARTCLOSED {
  142.   TICKET Ticket;
  143.   OP Type;
  144.   double Price;
  145.   double Stoploss;
  146.   datetime Time;
  147.   OBJECT_PARTCLOSED(TICKET Ticket_, OP Type_, double Price_, datetime Time_, double Stoploss_=0) {
  148.     Ticket = Ticket_ ;
  149.     Type = Type_ ;
  150.     Price = Price_ ;
  151.     Time = Time_ ;
  152.     Stoploss = Stoploss_ ;
  153.   }
  154.   OBJECT_PARTCLOSED(const OBJECT_PARTCLOSED &src) {
  155.     Ticket = src.Ticket ;
  156.     Type = src.Type ;
  157.     Price = src.Price ;
  158.     Time = src.Time ;
  159.     Stoploss = src.Stoploss ;
  160.   }
  161.   bool operator <(const OBJECT_PARTCLOSED &rhs) const {
  162.     //if(Ticket < rhs.Ticket) return true ;
  163.     if(Type < rhs.Type) return true ;
  164.     if(Price < rhs.Price) return true ;
  165.     if(Time < rhs.Time) return true ;
  166.     return false ;
  167.   }
  168. };
  169.  
  170. //===========================================================================
  171.  
  172. double UserLots, Lots, PrevBid, PrevAsk;
  173.  
  174. #define MAShift 0
  175.  
  176. datetime CurTime, TimeTick, StartTime, CancelTime, UserTime;
  177.  
  178. FLAG UserEntry = 0 ;
  179. bool FlushTL = false ;
  180.  
  181. // サーバーがストップロスを更新しなかった場合のトラップ対策用配列
  182. CArrayObj *StoplossTrapArray = NULL;
  183.  
  184. #define LOTSED_NAME        "EntryLots"
  185. #define LOTSDEC_NAME       "LotsDecBtn"
  186. #define LOTSINC_NAME       "LotsIncBtn"
  187. #define SELLBTN_NAME       "EntrySell"
  188. #define BUYBTN_NAME        "EntryBuy"
  189. #define CLOSEALLBTN_NAME   "CloseAll"
  190. #define CLOSELONGBTN_NAME  "CloseLong"
  191. #define CLOSESHORTBTN_NAME "CloseShort"
  192. #define FLUSHTLBTN_NAME    "FlushTL"
  193.  
  194. #define LOTSSAVE_NAME      (ENTRY_NAME "_UserLots_" + Symbol())
  195.  
  196. #define OFFTIME_NAME "OFF TIME"
  197. bool OffTimeVisible = false ;
  198.  
  199. #define AMOUNT_NAME "AMOUNT"
  200. #define AMOUNT_CLR_NEGA  ClrAmountNega
  201. #define AMOUNT_CLR_POSI  ClrAmountPosi
  202.  
  203. #define DBGINFO_NAME "DEBUG INFO"
  204.  
  205.   double AdjLots(double lots) {
  206.     lots = AdjustMarketLots(lots);
  207.     double roundLots = MathRound( MathMax(lots,StepLots) / StepLots ) ;
  208.     return MathMin(MathMax(roundLots*StepLots,MinLots),MaxLots) ;
  209.   }
  210.  
  211. //---------------------------------------------------------------------------
  212. int OnInit()
  213. {
  214.   //テスターで表示されるインジケータを非表示にする
  215.   HideTestIndicators(!DBGMODE);
  216.  
  217.   CurTime = MainTime();
  218.   TimeTick = StartTime = CancelTime = UserTime = BaseTime(TimeBase);
  219.  
  220.   GlobalSettings(
  221.     ENTRY_NAME,
  222.     Slippage,
  223.     Spread,
  224.     ORDER_RETRY,
  225.     ORDER_RETRY_SLEEP,
  226.     ORDER_RETRY_DURATION );
  227.  
  228.   OrderColorSetting(
  229.     ClrLongArrow,
  230.     ClrShortArrow );
  231.  
  232.   bool LotsLoaded = false ;
  233.   if(GlobalVariableCheck(LOTSSAVE_NAME)) {
  234.     UserLots = GlobalVariableGet(LOTSSAVE_NAME);
  235.     LotsLoaded = true ;
  236.   }
  237.  
  238.   UserLots = AdjLots(UserLots);
  239.   Lots = AdjLots(BaseLots) ; PrevBid = Bid ; PrevAsk = Ask ;
  240.  
  241.   //ストップロス更新確認用配列
  242.   StoplossTrapArray = new CArrayObj();
  243.   StoplossTrapArray.Sort(ARRAY_SORT_ASCEND);
  244.  
  245.   //DEBUG INFO
  246.   if(DBGMODE) {
  247.     ObjectCreate(DBGINFO_NAME, OBJ_LABEL, 0, 0, 0);
  248.     ObjectSet(DBGINFO_NAME, OBJPROP_XDISTANCE, 10);
  249.     ObjectSet(DBGINFO_NAME, OBJPROP_YDISTANCE, 15);
  250.     ObjectSet(DBGINFO_NAME, OBJPROP_CORNER, 3);
  251.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, "DEBUG INFO");
  252.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_FONT, "Verdana");
  253.     ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_FONTSIZE, 8);
  254.     ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_COLOR, clrAquamarine);
  255.   }
  256.  
  257.   //金額表示
  258.   if(ShowAmount) {
  259.     ObjectCreate(AMOUNT_NAME, OBJ_LABEL, 0, 0, 0);
  260.     ObjectSet(AMOUNT_NAME, OBJPROP_XDISTANCE, 20);
  261.     ObjectSet(AMOUNT_NAME, OBJPROP_YDISTANCE, 35);
  262.     ObjectSet(AMOUNT_NAME, OBJPROP_CORNER, 3);
  263.     ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, "0-");
  264.     ObjectSetString(0, AMOUNT_NAME, OBJPROP_FONT, "Verdana");
  265.     ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_FONTSIZE, 15);
  266.     ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
  267.   }
  268.  
  269.   //ユーザーエントリ用ボタン
  270.   if(ShowUserEntry) {
  271.  
  272.     int edit_y_pos = 20;
  273.     int btn_y_pos  = edit_y_pos + 24;
  274.  
  275.     // < 減らすボタン
  276.     ObjectCreate(0, LOTSDEC_NAME, OBJ_BUTTON, 0, 0, 0);
  277.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_XDISTANCE, 10);
  278.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_YDISTANCE, edit_y_pos);
  279.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_XSIZE, 20);
  280.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_YSIZE, 20);
  281.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_CORNER, 0);
  282.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_FONTSIZE, 10);
  283.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_COLOR, clrWhite);
  284.     ObjectSetInteger(0, LOTSDEC_NAME, OBJPROP_BGCOLOR, clrDimGray);
  285.     ObjectSetString (0, LOTSDEC_NAME, OBJPROP_TEXT, "<");
  286.     ObjectSetString (0, LOTSDEC_NAME, OBJPROP_FONT, "Verdana");
  287.  
  288.     // エディットボックス
  289.     ObjectCreate(0, LOTSED_NAME, OBJ_EDIT, 0, 0, 0);
  290.     ObjectSetInteger(0, LOTSED_NAME, OBJPROP_XDISTANCE, 31);
  291.     ObjectSetInteger(0, LOTSED_NAME, OBJPROP_YDISTANCE, edit_y_pos);
  292.     ObjectSetInteger(0, LOTSED_NAME, OBJPROP_XSIZE, 66);
  293.     ObjectSetInteger(0, LOTSED_NAME, OBJPROP_YSIZE, 20);
  294.     ObjectSetString (0, LOTSED_NAME, OBJPROP_TEXT, DoubleToString(UserLots,2)+(LotsLoaded?"":"-"));
  295.     ObjectSetInteger(0, LOTSED_NAME, OBJPROP_ALIGN, ALIGN_CENTER);
  296.     ObjectSetString(0, LOTSED_NAME, OBJPROP_TOOLTIP,
  297.       "Enter the lot size\n"
  298.       "Press the < > button, then dec/inc lots step by " + DoubleToString(StepLots, 2) + "\n"
  299.       "NOTE: It will be reset to the base lots if the text ends with a '-'" );
  300.  
  301.     // > 増やすボタン
  302.     ObjectCreate(0, LOTSINC_NAME, OBJ_BUTTON, 0, 0, 0);
  303.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_XDISTANCE, 98);
  304.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_YDISTANCE, edit_y_pos);
  305.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_XSIZE, 20);
  306.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_YSIZE, 20);
  307.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_CORNER, 0);
  308.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_FONTSIZE, 10);
  309.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_COLOR, clrWhite);
  310.     ObjectSetInteger(0, LOTSINC_NAME, OBJPROP_BGCOLOR, clrDimGray);
  311.     ObjectSetString (0, LOTSINC_NAME, OBJPROP_TEXT, ">");
  312.     ObjectSetString (0, LOTSINC_NAME, OBJPROP_FONT, "Verdana");
  313.  
  314.     //SELLボタン
  315.     ObjectCreate(SELLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  316.     ObjectSet(SELLBTN_NAME, OBJPROP_XDISTANCE, 10);
  317.     ObjectSet(SELLBTN_NAME, OBJPROP_YDISTANCE, btn_y_pos);
  318.     ObjectSet(SELLBTN_NAME, OBJPROP_XSIZE, 53);
  319.     ObjectSet(SELLBTN_NAME, OBJPROP_YSIZE, 27);
  320.     ObjectSet(SELLBTN_NAME, OBJPROP_CORNER, 0);
  321.     ObjectSet(SELLBTN_NAME, OBJPROP_FONTSIZE, 12);
  322.     ObjectSet(SELLBTN_NAME, OBJPROP_COLOR, White);
  323.     ObjectSet(SELLBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
  324.     ObjectSetString(0, SELLBTN_NAME, OBJPROP_TEXT, "SELL");
  325.     ObjectSetString(0, SELLBTN_NAME, OBJPROP_FONT, "Verdana");
  326.  
  327.     //BUYボタン
  328.     ObjectCreate(BUYBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  329.     ObjectSet(BUYBTN_NAME, OBJPROP_XDISTANCE, 65);
  330.     ObjectSet(BUYBTN_NAME, OBJPROP_YDISTANCE, btn_y_pos);
  331.     ObjectSet(BUYBTN_NAME, OBJPROP_XSIZE, 53);
  332.     ObjectSet(BUYBTN_NAME, OBJPROP_YSIZE, 27);
  333.     ObjectSet(BUYBTN_NAME, OBJPROP_CORNER, 0);
  334.     ObjectSet(BUYBTN_NAME, OBJPROP_FONTSIZE, 12);
  335.     ObjectSet(BUYBTN_NAME, OBJPROP_COLOR, White);
  336.     ObjectSet(BUYBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
  337.     ObjectSetString(0, BUYBTN_NAME, OBJPROP_TEXT, "BUY");
  338.     ObjectSetString(0, BUYBTN_NAME, OBJPROP_FONT, "Verdana");
  339.  
  340.   }
  341.  
  342.   int btn_ofs_x = 0 ;
  343.   const int btn_distance = 102 ;
  344.  
  345.   //全決済ボタン
  346.   if(ShowCloseAll) {
  347.     ObjectCreate(CLOSEALLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  348.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  349.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YDISTANCE, 35);
  350.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XSIZE, 100);
  351.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YSIZE, 25);
  352.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_CORNER, 2);
  353.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_FONTSIZE, 10);
  354.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_COLOR, White);
  355.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_BGCOLOR, /*clrDarkGreen*/clrDarkSlateGray);
  356.     ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_TEXT, "CLOSE ALL");
  357.     ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_FONT, "Verdana");
  358.     btn_ofs_x += btn_distance ;
  359.   }
  360.  
  361.   //LONG決済ボタン
  362.   if(ShowCloseLong) {
  363.     ObjectCreate(CLOSELONGBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  364.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  365.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YDISTANCE, 35);
  366.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XSIZE, 100);
  367.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YSIZE, 25);
  368.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_CORNER, 2);
  369.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_FONTSIZE, 10);
  370.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_COLOR, White);
  371.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
  372.     ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_TEXT, "CLOSE LONG");
  373.     ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_FONT, "Verdana");
  374.     btn_ofs_x += btn_distance ;
  375.   }
  376.  
  377.   //SHORT決済ボタン
  378.   if(ShowCloseShort) {
  379.     ObjectCreate(CLOSESHORTBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  380.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  381.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YDISTANCE, 35);
  382.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XSIZE, 100);
  383.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YSIZE, 25);
  384.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_CORNER, 2);
  385.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_FONTSIZE, 10);
  386.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_COLOR, White);
  387.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
  388.     ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_TEXT, "CLOSE SHORT");
  389.     ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_FONT, "Verdana");
  390.     btn_ofs_x += btn_distance ;
  391.   }
  392.  
  393.   //TLフラッシュ決算ボタン
  394.   if(ShowFlushTL) {
  395.     ObjectCreate(FLUSHTLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  396.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  397.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_YDISTANCE, 35);
  398.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_XSIZE, 100);
  399.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_YSIZE, 25);
  400.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_CORNER, 2);
  401.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_FONTSIZE, 10);
  402.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_COLOR, White);
  403.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_BGCOLOR, clrDarkSlateBlue);
  404.     ObjectSetString(0, FLUSHTLBTN_NAME, OBJPROP_TEXT, "FLUSH TL");
  405.     ObjectSetString(0, FLUSHTLBTN_NAME, OBJPROP_FONT, "Verdana");
  406.     btn_ofs_x += btn_distance ;
  407.  
  408.   }
  409.  
  410.   //ユーザーエントリをリセット
  411.   UserEntry=0;
  412.  
  413.   return(INIT_SUCCEEDED);
  414. }
  415. //---------------------------------------------------------------------------
  416. void OnDeinit(const int reason)
  417. {
  418.   if(ShowFlushTL) ObjectDelete(FLUSHTLBTN_NAME);
  419.   if(ShowCloseShort) ObjectDelete(CLOSESHORTBTN_NAME) ;
  420.   if(ShowCloseLong) ObjectDelete(CLOSELONGBTN_NAME) ;
  421.   if(ShowCloseAll) ObjectDelete(CLOSEALLBTN_NAME) ;
  422.   if(ShowUserEntry) {
  423.     string lots_str = ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT) ;
  424.     int ln = StringLen(lots_str);
  425.     if(ln>0) {
  426.       if(lots_str[ln-1]=='-') {
  427.         if(GlobalVariableCheck(LOTSSAVE_NAME))
  428.           GlobalVariableDel(LOTSSAVE_NAME);
  429.       }else {
  430.         double lots = StringToDouble(lots_str);
  431.         if(lots>0) {
  432.           lots = AdjLots(lots) ;
  433.           if(UserLots!=lots) {
  434.             UserLots = lots ;
  435.             GlobalVariableSet(LOTSSAVE_NAME, UserLots);
  436.           }
  437.         }
  438.       }
  439.     }
  440.     ObjectDelete(BUYBTN_NAME);
  441.     ObjectDelete(SELLBTN_NAME);
  442.     ObjectDelete(LOTSINC_NAME);
  443.     ObjectDelete(LOTSDEC_NAME);
  444.     ObjectDelete(LOTSED_NAME);
  445.   }
  446.   if(OffTimeVisible) {
  447.     ObjectDelete(OFFTIME_NAME) ;
  448.     OffTimeVisible=false ;
  449.   }
  450.   if(ShowAmount) {
  451.     ObjectDelete(AMOUNT_NAME) ;
  452.   }
  453.   if(DBGMODE) {
  454.     ObjectDelete(DBGINFO_NAME) ;
  455.   }
  456.   if(StoplossTrapArray!=NULL) {
  457.     delete StoplossTrapArray ;
  458.     StoplossTrapArray = NULL ;
  459.   }
  460. }
  461. //---------------------------------------------------------------------------
  462. void OnTick()
  463. {
  464.   datetime nextTime = MainTime() ;
  465.   bool nextTimed = nextTime != CurTime ;
  466.   CurTime = nextTime ;
  467.  
  468.   datetime nextTick = BaseTime(TimeBase) ;
  469.   bool nextTicked = nextTick != TimeTick ;
  470.   TimeTick = nextTick;
  471.  
  472.   // タイムコントロールチェック
  473.   CheckTimeControl(nextTicked);
  474.  
  475.   // 動作チェック
  476.   CheckBehavior(nextTimed);
  477.  
  478.   double atr14 = iATR(NULL,0,14,0) ;
  479.   double spread = Ask-Bid ;
  480.  
  481.   // デバッグ欄表示のサンプル
  482.   if(DBGMODE) {
  483.     DBGOUT(
  484.       // ATR in points
  485.       StringFormat("ATR(14): %.3f",atr14/Point) + " | " +
  486.       // SPREAD in points
  487.       StringFormat("SPREAD: %g",spread/Point) + " | " +
  488.       // 現在の値幅の変動倍率(ATR/SPREAD)
  489.       StringFormat("ATR(14)/SPREAD: %.3f",atr14/(spread<=0?1:spread))
  490.     );
  491.   }
  492.  
  493.   // エントリー処理
  494.   if(IsExpertEnabled()&&IsTradeAllowed()) {
  495.  
  496.     FLAG busy = AlreadyOrdered(FLAG_BUY|FLAG_SELL,MAGICMA) ;
  497.  
  498.     // ユーザーロット情報自動更新(ロットの最後が'-'で終わっている場合)
  499.     if(ShowUserEntry) {
  500.       string LotsStr = ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT) ;
  501.       int ln = StringLen(LotsStr);
  502.       if(ln>0) {
  503.         if(LotsStr[ln-1]=='-') {
  504.           if(UserLots!=Lots) {
  505.             UserLots = Lots;
  506.             ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT, DoubleToString(UserLots, 2)+"-");
  507.           }
  508.         }
  509.       }
  510.     }
  511.  
  512.     // ユーザーの注文
  513.     if(UserEntry) {
  514.  
  515.       // ユーザーのエントリを確認
  516.       if(TimeTick-UserTime<60) {  // 発行されてから60秒以内の注文
  517.  
  518.         FLAG user = UserEntry ;
  519.  
  520.         // 注文
  521.         if(user/*&&!AlreadyOrdered(user,MAGICMA)*/) {
  522.  
  523.           // ユーザーロット取得と更新
  524.           if(ShowUserEntry) {
  525.             double lots = StringToDouble(ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT));
  526.             if(lots>0) {
  527.               lots = AdjLots(lots) ;
  528.               if(UserLots!=lots) {
  529.                 UserLots = lots ;
  530.                 GlobalVariableSet(LOTSSAVE_NAME, UserLots);
  531.               }
  532.             }
  533.           }
  534.  
  535.           OP entry = user == FLAG_BUY ? OP_BUY : OP_SELL ;
  536.           if(EntryManualPosition("USER", entry, UserLots)>=0)
  537.             busy |= user ;
  538.           else {
  539.             PrintMessage("Order failed by USER.");
  540.             PlaySound("timeout.wav");
  541.           }
  542.           UserEntry = 0 ;
  543.         }
  544.  
  545.       }else { UserEntry=0; }
  546.  
  547.     }
  548.  
  549.     // MARK: 自動注文
  550.  
  551.     /*
  552.     do {
  553.  
  554.       // 自動注文 開始時間調整
  555.       if(StartTime>TimeTick||CancelTime>TimeTick)
  556.         break ;
  557.  
  558.       // スプレッド幅のチェック
  559.       if(MarketInfo(NULL,MODE_SPREAD) > Spread)
  560.         break ;
  561.  
  562.       // 自動注文 XMA+ZigZag Detector
  563.       if(nextTimed)
  564.         EAEntryXMAZigZagPosition(busy,1);
  565.  
  566.     }while(0);
  567.     */
  568.  
  569.   }else {
  570.  
  571.     if(StartTime-TimeTick<10)
  572.       StartTime = TimeTick+10 ;
  573.  
  574.   }
  575.  
  576.   /*
  577.   if(PmdTiming) {
  578.     PmdPrevBid = (PmdPrevBid+Bid)/2.0 ; PmdPrevAsk = (PmdPrevAsk+Ask)/2.0 ;
  579.   }*/
  580.   PrevBid = Bid ; PrevAsk = Ask ;
  581. }
  582. //---------------------------------------------------------------------------
  583. void OnChartEvent(
  584.   const int id,
  585.   const long &lparam,
  586.   const double &dparam,
  587.   const string &sparam
  588.  )
  589. {
  590.   if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == LOTSED_NAME) {
  591.       string lotsStr = ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT);
  592.       int ln = StringLen(lotsStr);
  593.       bool invalid = true ;
  594.       if(ln > 0 && lotsStr[ln-1] != '-') {
  595.           // 数値として評価してチェック
  596.           double lots = StringToDouble(lotsStr);
  597.           if(lots > 0) {
  598.               // 正常値 → AdjLots で丸めて反映
  599.               lots = AdjLots(lots);
  600.               UserLots = lots;
  601.               GlobalVariableSet(LOTSSAVE_NAME, UserLots);
  602.               ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT,
  603.                               DoubleToString(UserLots, 2));
  604.               invalid = false ; // 適正値
  605.           }
  606.       }
  607.       if(invalid) { // 不正値、または、自動ロット設定値("-"で終わる場合)
  608.         UserLots = Lots;
  609.         ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT,
  610.                         DoubleToString(Lots, 2) + "-");
  611.       }
  612.   }
  613.   if(id == CHARTEVENT_OBJECT_CLICK &&
  614.      (sparam == LOTSDEC_NAME || sparam == LOTSINC_NAME)) {
  615.       double lots = StringToDouble(ObjectGetString(0, LOTSED_NAME, OBJPROP_TEXT));
  616.       lots += (sparam == LOTSINC_NAME ? +StepLots : -StepLots);
  617.       lots  = AdjLots(lots);
  618.       UserLots = lots;
  619.       GlobalVariableSet(LOTSSAVE_NAME, UserLots);
  620.       ObjectSetString(0, LOTSED_NAME, OBJPROP_TEXT, DoubleToString(UserLots, 2));
  621.       Sleep(100);
  622.       ObjectSetInteger(0, sparam, OBJPROP_STATE, false);
  623.   }
  624.   if( ( sparam == CLOSEALLBTN_NAME ||
  625.         sparam == CLOSELONGBTN_NAME ||
  626.         sparam == CLOSESHORTBTN_NAME ) && id==CHARTEVENT_OBJECT_CLICK) {
  627.     int orderFlag = 0 ;
  628.     if(sparam == CLOSEALLBTN_NAME) orderFlag = FLAG_SELL | FLAG_BUY ;
  629.     else if(sparam == CLOSELONGBTN_NAME) orderFlag = FLAG_BUY ;
  630.     else if(sparam == CLOSESHORTBTN_NAME) orderFlag = FLAG_SELL ;
  631.     CheckoutOrders(orderFlag);
  632.     Sleep(100);
  633.     ObjectSet(sparam, OBJPROP_STATE, False);
  634.     // 60秒エントリーを停止する
  635.     CancelTime = TimeTick + 60 ;
  636.   }
  637.   if(sparam == FLUSHTLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  638.     FlushTL=true;
  639.     Sleep(100);
  640.     ObjectSet(FLUSHTLBTN_NAME, OBJPROP_STATE, False);
  641.   }
  642.   if(sparam == SELLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  643.     { UserEntry = FLAG_SELL ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
  644.     Sleep(100);
  645.     ObjectSet(SELLBTN_NAME, OBJPROP_STATE, False);
  646.   }
  647.   if(sparam == BUYBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  648.     { UserEntry = FLAG_BUY ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
  649.     Sleep(100);
  650.     ObjectSet(BUYBTN_NAME, OBJPROP_STATE, False);
  651.   }
  652. }
  653. //---------------------------------------------------------------------------
  654. //DBGOUT
  655. void DBGOUT(string text)
  656. {
  657.   if(DBGMODE) {
  658.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, text);
  659.   }
  660. }
  661. //---------------------------------------------------------------------------
  662. //タイムコントロールチェック
  663. void CheckTimeControl(bool nextTicked)
  664. {
  665.   if(!TimeControl) {
  666.     if(OffTimeVisible) {
  667.       ObjectDelete(OFFTIME_NAME);
  668.       OffTimeVisible = false ;
  669.     }
  670.     return ;
  671.   }
  672.   if(!nextTicked) return ;
  673.   if(!ControlTimeAction(
  674.       TimeTick,StringToTime(TimeStart),StringToTime(TimeEnd),
  675.       StartTime,MAGICMA,TimeAction)) {
  676.     datetime timOff = StartTime - TimeTick ;
  677.     if(!OffTimeVisible) {
  678.       // OFF TIME テキストを表示
  679.       ObjectCreate(OFFTIME_NAME, OBJ_LABEL, 0, 0, 0);
  680.       ObjectSet(OFFTIME_NAME, OBJPROP_XDISTANCE, 10);
  681.       ObjectSet(OFFTIME_NAME, OBJPROP_YDISTANCE, 25);
  682.       ObjectSet(OFFTIME_NAME, OBJPROP_CORNER, 1);
  683.       ObjectSetString(0, OFFTIME_NAME, OBJPROP_TEXT, "OFF TIME");
  684.       ObjectSetString(0, OFFTIME_NAME, OBJPROP_FONT, "Verdana");
  685.       ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_FONTSIZE, 8);
  686.       ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_COLOR, ClrTimeControl);
  687.       OffTimeVisible = true ;
  688.     }
  689.   }else if(OffTimeVisible) {
  690.     ObjectDelete(OFFTIME_NAME);
  691.     OffTimeVisible = false ;
  692.   }
  693. }
  694. //---------------------------------------------------------------------------
  695. //メインタイムを返す
  696. datetime MainTime(int shift=0)
  697. {
  698.   return iTime(Symbol(), MainTimeFrame, shift);
  699. }
  700. //---------------------------------------------------------------------------
  701. //メインPERIODを返す
  702. int MainPeriod()
  703. {
  704.   int period = MainTimeFrame ;
  705.   if(!period) period = Period();
  706.   return period ;
  707. }
  708. //---------------------------------------------------------------------------
  709. //金額表示の更新
  710. void UpdateAmount(double amount, int positions)
  711. {
  712.   if(ShowAmount) {
  713.     if(positions>0) {
  714.       string s = DoubleToAmount(amount,AmountDig) ;
  715.       if(amount>0) s = "+" + s ;
  716.       ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s);
  717.       if(amount<0)
  718.         ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_NEGA);
  719.       else
  720.         ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
  721.     }else {
  722.       string s = ObjectGetString(0, AMOUNT_NAME, OBJPROP_TEXT);
  723.       int ln=StringLen(s);
  724.       if(ln>0) {
  725.         if(s[ln-1]!='-')
  726.           ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s+"-");
  727.       }
  728.     }
  729.   }
  730. }
  731. //---------------------------------------------------------------------------
  732. //MARK:動作チェック
  733. void CheckBehavior(bool nextTimed)
  734. {
  735.   // 複利ロット計算
  736.   if(Compounding) {
  737.     double balance = AccountBalance();
  738.     if(BalanceIncludeCredit) balance += AccountCredit();
  739.     Lots = balance*BaseLots/CompoundingBase ;
  740.     if(Lots<MinLots) Lots = MinLots ;
  741.     if(Lots>MaxLots) Lots = MaxLots ;
  742.   }
  743.  
  744.   // 全体のステータスを取得
  745.   STATUS BuyWholeStatus, SellWholeStatus ;
  746.   for(int n=0;n<2;n++) {
  747.     CheckStatus(OP_BUY, MAGICMA, &BuyWholeStatus);
  748.     BuyWholeStatus.OrdersSort(ORDERSORT_PRICE_ASCEND);
  749.     if(!CheckoutStoplossTrappedOrders(&BuyWholeStatus)) break;
  750.   }
  751.   for(int n=0;n<2;n++) {
  752.     CheckStatus(OP_SELL, MAGICMA, &SellWholeStatus);
  753.     SellWholeStatus.OrdersSort(ORDERSORT_PRICE_DESCEND);
  754.     if(!CheckoutStoplossTrappedOrders(&SellWholeStatus)) break;
  755.   }
  756.   StoplossTrapArray.Clear();
  757.  
  758.   // 金額を更新
  759.   double CurAmount = BuyWholeStatus.GrossProfit+SellWholeStatus.GrossProfit ;
  760.   int CurPositions = BuyWholeStatus.Positions+SellWholeStatus.Positions ;
  761.   UpdateAmount(CurAmount,CurPositions);
  762.  
  763.   // 自動処理
  764.   if(Automation) {
  765.  
  766.     // 最大損益のチェック
  767.     if(CurAmount<0) {
  768.       double balance = AccountBalance();
  769.       if(BalanceIncludeCredit) balance += AccountCredit();
  770.       if(balance*MaxGrosslossPer/100.0<-CurAmount) {
  771.         //最大損益を超えた場合は、すべて決済する
  772.         CheckoutOrders(FLAG_BUY|FLAG_SELL);
  773.         PrintMessage("Check-out orders by over Maximum Gross Loss");
  774.         return;
  775.       }
  776.     }
  777.  
  778.     // オーダーの処理
  779.     ProcessOrders(nextTimed, OP_BUY, BuyWholeStatus, SellWholeStatus);
  780.     ProcessOrders(nextTimed, OP_SELL, SellWholeStatus, BuyWholeStatus);
  781.  
  782.   }
  783.  
  784.   FlushTL=false;
  785. }
  786. //---------------------------------------------------------------------------
  787. //MARK:オーダーの処理
  788. void ProcessOrders(bool nextTimed, OP orderType, const STATUS &status, const STATUS &revStatus)
  789. {
  790.   if(status.Positions<=0) return ;
  791.  
  792.   // トレーリング
  793.   if(Trailing) {
  794.     double tstart = TrailingStart*Point ;
  795.     double tstop = TrailingStop*Point ;
  796.     double minPadding = tstart+tstop ;
  797.     for(int i=0;i<status.OrdersCount();i++) {
  798.       COrderStatus *order = status.OrdersAt(i) ;
  799.       if((order.Tag&STATAG_CHECKEDOUT)!=0) continue ; // 決済済
  800.       if( orderType==OP_BUY ?
  801.             order.Price>Bid-minPadding : order.Price<Ask+minPadding )
  802.         break;
  803.       double sl=0.0 ;
  804.       if( order.Stoploss==0.0 ||
  805.           ( orderType==OP_BUY ?
  806.               order.Stoploss<order.Price : order.Stoploss>order.Price ) ) {
  807.         //初回トレール
  808.         sl = orderType==OP_BUY ? order.Price+tstart : order.Price-tstart ;
  809.       }else {
  810.         //既にトレール済
  811.         sl = order.Stoploss ;
  812.       }
  813.       while( ( orderType==OP_BUY ? Bid-sl : sl-Ask ) >= tstop*2 ) {
  814.         //カクカクにトレール幅を狭めていく
  815.         sl += orderType==OP_BUY ? +tstop : -tstop ;
  816.       }
  817.       if(!InnerPoint(sl,order.Stoploss)) {
  818.         //ストップロスを更新
  819.         if(ModifyOrderSlTp(order.Ticket,sl,order.Takeprofit)) {
  820.           order.Stoploss = sl ;
  821.           EntryStoplossTrap(orderType, order, sl);
  822.         }else PrintLastError();
  823.       }
  824.     }
  825.   }
  826.  
  827.   // 3EMA処理
  828.   if(MA3 && (nextTimed||FlushTL)) {
  829.     double HalfSpread = (Ask-Bid)/2.0;
  830.     double FastMA0 = iMA(NULL, MainTimeFrame, MA3FastPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  831.     double MediumMA0 = iMA(NULL, MainTimeFrame, MA3MediumPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  832.     double SlowMA0 = iMA(NULL, MainTimeFrame, MA3SlowPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  833.     for(int i=0;i<status.OrdersCount();i++) {
  834.       COrderStatus *order = status.OrdersAt(i) ;
  835.       if((order.Tag&STATAG_CHECKEDOUT)!=0) continue ; // 決済済
  836.       double price = order.Price ;
  837.       double sl = order.Stoploss ;
  838.       double trail_sl=0.0;
  839.       double checkout_denom=0.0;
  840.       string checkout_reason="";
  841.       if(InnerPoint(sl,price)) { // プライスがslに一致
  842.         if(FlushTL&&!nextTimed) continue;
  843.         if(!InnerPoint(MediumMA0,price) &&
  844.           (orderType==OP_BUY?MediumMA0-HalfSpread>price:MediumMA0+HalfSpread<price)) { // Medium MA がプライス以上
  845.           if(orderType==OP_BUY?FastMA0>Ask:FastMA0<Bid) { // Fast MA が現価以上
  846.             // 決済設定
  847.             checkout_denom = LotsDenomMAFast ;
  848.             checkout_reason = "Check-out by Fast MA" ;
  849.             if(orderType==OP_BUY?MediumMA0>Ask:MediumMA0<Bid) // Medium MA が現価より上
  850.             { checkout_reason += " & Medium MA"; checkout_denom = 1.0 ;} // 全決済する
  851.             // ストップロスを Medium MA 値に更新する
  852.             trail_sl = MediumMA0 + (orderType==OP_BUY?-HalfSpread:+HalfSpread) ;
  853.           }
  854.         }
  855.       }else if(sl!=0.0&&(orderType==OP_BUY?sl>price:sl<price)) { //プライスがslより下
  856.         if(FlushTL&&!nextTimed) continue;
  857.         if(orderType==OP_BUY?Ask<=MediumMA0:Bid>=MediumMA0) { //現価が Medium MA より下になった
  858.           // 決済設定
  859.           checkout_denom = 1.0 ; // 全決済
  860.           checkout_reason = "Check-out by Medium MA" ;
  861.         }
  862.       }else { //プライスがslより上、もしくは、slが設定されていない
  863.         if(FlushTL||MA3TLPeriod>0) { // TL(TimeLimited) ポジションが有効
  864.           //ロウソク足の期間を計測
  865.           /* 旧方式
  866.           datetime tperiod = MainPeriod() * 60 ;
  867.           int period = int((CurTime-order.OpenTime)/tperiod);
  868.           bool overTime = period>=MA3TLPeriod-1 ;
  869.           */
  870.           // 新方式
  871.           int period = iBarShift(_Symbol, MainTimeFrame, order.OpenTime);
  872.           bool overTime = period>=MA3TLPeriod ;
  873.           if(FlushTL||overTime) { //TL(TimeLimited)期間が過ぎている
  874.             if(orderType==OP_BUY?Bid>price:Ask<price) { // 利確できる位置にある
  875.               if(!FlushTL&&(orderType==OP_BUY?FastMA0>Ask||MediumMA0>Ask:FastMA0<Bid||MediumMA0<Bid)) { // 2MA が現価より上
  876.                 // 現価が 2MA を抜かすまでの間、ストップロスを建値ギリギリまで引き上げておく
  877.                 trail_sl = price + (orderType==OP_BUY?-Point:+Point);
  878.               }else { // FastMA が現価以下
  879.                 // 決済設定
  880.                 checkout_denom = LotsDenomTL ;
  881.                 checkout_reason = "Check-out by TL(TimeLimited)" ;
  882.                 // ストップロスを建値に引き上げる
  883.                 trail_sl = price ;
  884.               }
  885.             }
  886.           }
  887.         }
  888.         if(!FlushTL||nextTimed) {
  889.           if(sl==0.0) { //ストップロスが設定されていない
  890.             if(MaxGrosslossPer>=100.0) { // Max Gross loss が 100%以上
  891.               if(orderType==OP_BUY?Ask<=SlowMA0:Bid>=SlowMA0) { //現価が Slow MA より下になった
  892.                 // 損切設定
  893.                 checkout_denom = 1.0 ; // 全決済
  894.                 checkout_reason = "Loss-cut order by Slow MA" ;
  895.               }
  896.             }
  897.           }
  898.         }
  899.       }
  900.       if(trail_sl!=0.0) {
  901.         //MAによるトレーリング
  902.         if(sl==0.0||(!InnerPoint(sl,trail_sl)&&(orderType==OP_BUY?sl<trail_sl:sl>trail_sl))) {
  903.           sl = trail_sl ;
  904.           if(ModifyOrderSlTp(order.Ticket,sl,order.Takeprofit)) {
  905.             order.Stoploss = sl ;
  906.             EntryStoplossTrap(orderType, order, sl);
  907.           }else PrintLastError();
  908.         }
  909.       }
  910.       if(checkout_denom>0.0) {
  911.         //MAによる決済処理
  912.         double lots = AdjLots(order.Lots/checkout_denom) ;
  913.         if(lots<MinLots) lots = MinLots ;
  914.         if(lots>order.Lots) lots = order.Lots ;
  915.         if(CheckoutOrder(orderType,order.Ticket,lots)) {
  916.           PrintMessage(checkout_reason);
  917.           order.Lots -= lots ;
  918.           if(order.Lots<=0)
  919.              order.Tag |= STATAG_CHECKEDOUT ; // 決済済
  920.         }
  921.       }
  922.     }
  923.   }
  924. }
  925. //---------------------------------------------------------------------------
  926. //マニュアルポジション発注
  927. TICKET EntryManualPosition(string detector, OP entryType, double lots)
  928. {
  929.   double sl=0.0, tp=0.0;
  930.   switch(entryType)  {
  931.     case OP_BUY:
  932.       if(Stoploss!=0.0) sl = Ask-Stoploss*Point ;
  933.       if(Takeprofit!=0.0) tp = Ask+Takeprofit*Point ;
  934.       break;
  935.     case OP_SELL:
  936.       if(Stoploss!=0.0) sl = Bid+Stoploss*Point ;
  937.       if(Takeprofit!=0.0) tp = Bid-Takeprofit*Point ;
  938.       break;
  939.   }
  940.   if(sl==0.0) {
  941.     if(MaxGrosslossPer>=100.0) {
  942.       // SlowMAの現在位置がAsk/Bidよりも上回っていないことを確認する
  943.       double HalfSpread = (Ask-Bid)/2.0;
  944.       double SlowMA0 = iMA(NULL, MainTimeFrame, MA3SlowPeriod, MAShift, MAMode, MAPriceType, 0) +HalfSpread ;
  945.       if(entryType==OP_BUY?SlowMA0>=Ask:SlowMA0<=Bid) {
  946.         PrintMessage("Entring failed due to Slow MA over price reached");
  947.         return -1 ; // invalid
  948.       }
  949.     }
  950.   }
  951.   return MakeOrder(entryType,lots,sl,tp,detector,MAGICMA);
  952. }
  953. //---------------------------------------------------------------------------
  954. //マジックナンバーと一致する全オーダーのチェックアウト
  955. void CheckoutOrders(FLAG flag)
  956. {
  957.   CheckoutOrderAll(flag,MAGICMA);
  958. }
  959. //---------------------------------------------------------------------------
  960. // オーダーを StoplossTrapArray に登録
  961. bool EntryStoplossTrap(OP type, const COrderStatus *order, double stoploss=0)
  962. {
  963.   if(stoploss==0) stoploss = order.Stoploss ;
  964.   if(stoploss==0) return false ;
  965.   OBJECT_PARTCLOSED part(order.Ticket,type,order.Price,order.OpenTime,stoploss);
  966.   int idx = SearchSortedArray(StoplossTrapArray,part);
  967.   if(idx>=0) { // 既にエントリ済
  968.     CSortable<OBJECT_PARTCLOSED>* obj =
  969.       (CSortable<OBJECT_PARTCLOSED>*)StoplossTrapArray.At(idx) ;
  970.     obj.v.Stoploss = stoploss ; // ストップロスの値を更新
  971.   }else { // 新規エントリ
  972.     AddToSortedArray(StoplossTrapArray,part);
  973.   }
  974.   return true ;
  975. }
  976. //---------------------------------------------------------------------------
  977. // オーダーのストップロスが前回登録したストップロス情報と一致しているか調べる
  978. bool CheckStoplossTrap(OP type, const COrderStatus *order, double stoploss=0)
  979. {
  980.   if(stoploss==0) stoploss = order.Stoploss ;
  981.   if(stoploss==0) return true ; // 無視
  982.   OBJECT_PARTCLOSED part(order.Ticket,type,order.Price,order.OpenTime,stoploss);
  983.   int idx = SearchSortedArray(StoplossTrapArray,part);
  984.   if(idx>=0) { // 既にエントリ済
  985.     CSortable<OBJECT_PARTCLOSED>* obj =
  986.       (CSortable<OBJECT_PARTCLOSED>*)StoplossTrapArray.At(idx) ;
  987.     return InnerPoint(obj.v.Stoploss, stoploss); // ストップロスの一致を返す
  988.   }
  989.   return true ; // エントリされていないので無視
  990. }
  991. //---------------------------------------------------------------------------
  992. // ストップロスが更新されていないオーダーを全て決済する
  993. int CheckoutStoplossTrappedOrders(STATUS *status)
  994. {
  995.   int n=0;
  996.   for(int i=status.OrdersCount()-1;i>=0;i--) {
  997.     COrderStatus *order = status.OrdersAt(i);
  998.     if((order.Tag&STATAG_CHECKEDOUT)!=0) continue ;
  999.     if(!CheckStoplossTrap(status.Type,order)) {
  1000.       if(CheckoutOrder(status.Type,order.Ticket,order.Lots)) {
  1001.         order.Lots = 0 ;
  1002.         order.Tag |= STATAG_CHECKEDOUT ;
  1003.         PrintMessage("Checkout Order by ST(StoplossTrapped)");
  1004.         n++;
  1005.       }
  1006.     }
  1007.   }
  1008.   return n;
  1009. }
  1010. //---------------------------------------------------------------------------
  1011.  
Tags: Mt4
Advertisement
Add Comment
Please, Sign In to add comment