HYROLEAN

test_3ma_user_v2.mq5

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