HYROLEAN

test_3ma_pyramid_ofs.mq4

Dec 7th, 2024 (edited)
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 81.50 KB | Money | 0 0
  1. #property copyright "2024, (c)hyrolean"
  2. #property link      "https://pastebin.com/ADhjs5D1"
  3. #property version   "1.12"
  4. #property strict
  5.  
  6. #include <stdlib.mqh>
  7.  
  8.   // 3EMA https://youtu.be/GsAAMgKXzic
  9.  
  10. #define ENTRY_NAME "3MAPyramid"
  11.  
  12. enum ENUM_POSI {
  13.   POSI_STOP,                  // Stop
  14.   POSI_ONLY_LONG,             // Only Long
  15.   POSI_ONLY_SHORT,            // Only Short
  16.   POSI_HALF_LONG_AND_SHORT,   // Long & Short (Half duplex)
  17.   POSI_FULL_LONG_AND_SHORT    // Long & Short (Full duplex)
  18. };
  19.  
  20. enum ENUM_TIMEBASE {
  21.   TIMEBASE_GMT,               // Greenwich Mean Time (GMT)
  22.   TIMEBASE_LOCAL,             // Local Time
  23.   TIMEBASE_SERVER             // Server Time
  24. };
  25.  
  26. enum ENUM_TIMEACT {
  27.   TIMEACT_NONE,               // None ( EA closes positions automatically )
  28.   TIMEACT_FORCE_CLOSE_ALL,    // Force Close All positions
  29.   TIMEACT_FORCE_CLOSE_LONG,   // Force Close Long positions
  30.   TIMEACT_FORCE_CLOSE_SHORT,  // Force Close Short positions
  31.   TIMEACT_SOFT_CLOSE_ALL,     // Close All positions if profits are Positive
  32.   TIMEACT_SOFT_CLOSE_LONG,    // Close Long positions if profits are Positive
  33.   TIMEACT_SOFT_CLOSE_SHORT    // Close Short positions if profits are Positive
  34. };
  35.  
  36. input ENUM_POSI ActivePositions = POSI_HALF_LONG_AND_SHORT; // Active Entry Positions
  37. input ENUM_TIMEFRAMES MainTimeFrame = PERIOD_M5; // Main Time Frame
  38. input int       MAGICMA         = 35835;   // Magic Number
  39. input bool      TimeControl     = false;   // Time Control
  40. input ENUM_TIMEBASE TimeBase    = TIMEBASE_LOCAL; // Time Base
  41. input string    TimeStart       = "09:00"; // Time Start
  42. input string    TimeEnd         = "15:00"; // Time End
  43. input ENUM_TIMEACT TimeAction   = TIMEACT_NONE; // Time Action when time end reached
  44. input int       Slippage        = 10;      // Max slippage
  45. input int       Spread          = 50;      // Max spread in points
  46. input double    BaseLots        = 0.02;    // Base lots
  47. input double    MinLots         = 0.01;    // Minimum lots
  48. input double    MaxLots         = 100.0;   // Maximum lots
  49. input double    ProfitTotalLots = 1.00;    // Profit Taking total lots
  50. input double    ProfitRatePer   = 33.3;    // Profit Rate in percentage
  51. input int       ProfitKeepTL    = 3;       // Profit keeping TL(TimeLimited) period
  52. input bool      EntryTLPos      = true;    // Entry TL(TimeLimited) positions
  53. input bool      EntryFastMAPos  = true;    // Entry Fast MA positions
  54. input bool      EntryMediumMAPos= true;    // Entry Medium MA positions
  55. input ENUM_MA_METHOD      MAMode= MODE_EMA;// MA mode
  56. input ENUM_APPLIED_PRICE  MAPriceType = PRICE_CLOSE; // MA price type
  57. input int       FastMAPeriod    = 10;      // Fast MA period
  58. input int       MediumMAPeriod  = 20;      // Medium MA period
  59. input int       SlowMAPeriod    = 50;      // Slow MA period
  60. input bool      ReferSlowMA     = false;   // Refer Slow MA
  61. input double    Takeprofit      = 540;     // Take profit in points
  62. input double    Stoploss        = 360;     // Stop loss in points
  63. input double    PyramidingStride= 80.0;    // Pyramiding price Stride in points
  64. input double    PyramidingScale = 1.0;     // Pyramiding lots Multiplier
  65. input int       PyramidingTimes = 30;      // Pyramiding max Positions (0=infinite)
  66. input int       PyramidingInterval=0;      // Pyramiding Interval in sec (0=continuous)
  67. input bool      Averaging       = false;   // Averaging enabled (averaging down and martingale)
  68. input int       AveragingTimes  = 20;      // Averaging max Positions (0=infinite)
  69. input double    AveragingScale  = 1.0;     // Averaging lots Multiplier
  70. input bool      Offsetting      = true;    // Offsetting Enabled (divergence entriable)
  71. input int       OffsettingExpireMinutes=0; // Offsetting Order Expire minutes (0=unlimited)
  72. input double    OffsettingDvgnScale=0.1;   // Offsetting Divergence lots Multiplier
  73. input bool      Trailing        = false;   // Trailing Enabled
  74. input double    TrailingStart   = 100;     // Trailing Start in points
  75. input double    TrailingPadding = 50;      // Trailing Padding in points
  76. input bool      Scalping        = false;   // Scalping Enabled
  77. input double    ScalpingProfit  = 500;     // Scalping Border of Gross Profit (0.0=n/a)
  78. input double    ScalpingLoss    = -1000;   // Scalping Border of Gross Loss (0.0=n/a)
  79. input int       ScalpingInterval= 5;       // Scalping Interval in sec (0=continuous)
  80. input bool      ScalpingIgnoreTL= false;   // Scalping also after TL(TimeLimited) reached
  81. input group     "Appearance Settings"
  82. input bool      ShowUserEntry   = true;    // Show user entry SELL/BUY buttons
  83. input bool      ShowCloseAll    = true;    // Show a CLOSE ALL button
  84. input bool      ShowCloseLong   = false;   // Show a CLOSE LONG button
  85. input bool      ShowCloseShort  = false;   // Show a CLOSE SHORT button
  86. input bool      ShowAmount      = true;    // Show Current Amount
  87. input int       AmountDig       = 0;       // Amount Number of decimal places
  88. input group     "Color Settings"
  89. input color     ClrAmountPosi   = clrLightGoldenrod; // Amount Positive color
  90. input color     ClrAmountNega   = clrLightPink; // Amount Negative color
  91. input color     ClrTimeControl  = clrYellow; // Time Control Status color
  92. input color     ClrLongBorder   = clrDeepSkyBlue; // Long Border color
  93. input color     ClrShortBorder  = clrViolet; // Short Border color
  94. input color     ClrTrailBorder  = clrLime; // Trailing Border color
  95. input color     ClrLongArrow    = clrBlue; // Long Arrow color
  96. input color     ClrShortArrow   = clrRed;  // Short Arrow color
  97. input group     "DEBUG Setting"
  98. input bool      DBGMODE         = true;    // DEBUG MODE
  99.  
  100. double Lots, PrevBid, PrevAsk;
  101.  
  102. #define MAShift 0
  103.  
  104. bool PmdTiming=false;
  105. double PmdPrevBid, PmdPrevAsk;
  106. datetime CurTime, CurPmdInt, CurSclpInt, TimeTick, StartTime, CancelTime, UserTime;
  107. int BuyKeepTimer=0, SellKeepTimer=0, BuyLosscutTimer=0, SellLosscutTimer=0;
  108. bool BuyTLEntried=false, BuyFastMAEntried=false, BuyMediumMAEntried=false;
  109. bool SellTLEntried=false, SellFastMAEntried=false, SellMediumMAEntried=false;
  110.  
  111. #define ORDER_RETRY  10
  112.  
  113. #define FLAG_BUY      1
  114. #define FLAG_SELL     2
  115. #define FLAG_DUPLEX   4
  116.  
  117. int PositionFlag = FLAG_BUY | FLAG_SELL | FLAG_DUPLEX ;
  118. int UserEntry = 0 ;
  119.  
  120. #define SELLBTN_NAME       "EntrySell"
  121. #define BUYBTN_NAME        "EntryBuy"
  122. #define CLOSEALLBTN_NAME   "CloseAll"
  123. #define CLOSELONGBTN_NAME  "CloseLong"
  124. #define CLOSESHORTBTN_NAME "CloseShort"
  125.  
  126. #define BUYBORDER_NAME "LONG BORDER"
  127. #define SELLBORDER_NAME "SHORT BORDER"
  128. bool BuyBorderLined = false, SellBorderLined = false ;
  129.  
  130. #define BUYTRAIL_NAME "LONG SL"
  131. #define SELLTRAIL_NAME "SHORT SL"
  132. bool BuyTrailLined = false, SellTrailLined = false ;
  133.  
  134. #define OFFTIME_NAME "OFF TIME"
  135. bool OffTimeVisible = false ;
  136.  
  137. #define AMOUNT_NAME "AMOUNT"
  138. #define AMOUNT_CLR_NEGA  ClrAmountNega
  139. #define AMOUNT_CLR_POSI  ClrAmountPosi
  140.  
  141. // BuyMaxPrice/SellMinPrice
  142. #define BUYMAXPRICE_NAME (ENTRY_NAME "_BuyMaxPrice_" +Symbol())
  143. #define SELLMINPRICE_NAME (ENTRY_NAME "_SellMinPrice_" +Symbol())
  144. double BuyMaxPrice, SellMinPrice ;
  145.  
  146. // LossPrices
  147. #define LOSSPRICES_NAME (ENTRY_NAME "_LossPrices_" + Symbol())
  148. double LossPrices=0.0;
  149.  
  150.  
  151. #define DBGINFO_NAME "DEBUG INFO"
  152.  
  153. //---------------------------------------------------------------------------
  154. //エラーログ出力
  155. void PrintLastError()
  156. {
  157.   int lastError = GetLastError() ;
  158.   printf(ENTRY_NAME"(%s): error(%d): %s",
  159.     Symbol(),lastError,ErrorDescription(lastError));
  160. }
  161. //---------------------------------------------------------------------------
  162. //オブジェクトのソート
  163. // ( https://youtu.be/ZRPiwUNLjiA )
  164. #include <Arrays/ArrayObj.mqh>
  165. #define ARRAY_SORT_ASCEND 1
  166. #define ARRAY_SORT_DESCEND 2
  167. template <typename T>
  168. class CSortable : public CObject {
  169. public:
  170.     T key;
  171.     int Compare(const CObject *node, const int mode=0) const {
  172.       if(mode<=0) return 0;
  173.       CSortable *comp= (CSortable*)node ;
  174.       bool f = key<comp.key ;
  175.       if(!f&&!(comp.key<key)) return 0;
  176.       int result = f ? -1:+1 ;
  177.       switch(mode) {
  178.         case ARRAY_SORT_ASCEND:  return +result;
  179.         case ARRAY_SORT_DESCEND: return -result;
  180.       }
  181.       return 0;
  182.     }
  183. };
  184. template <typename T>
  185. void AddToArray(CArrayObj &array, const T& key) {
  186.   CSortable<T> *node = new CSortable<T>();
  187.   node.key=key;
  188.   array.Add(node);
  189. }
  190. //---------------------------------------------------------------------------
  191. int OnInit()
  192. {
  193.   //テスターで表示されるインジケータを非表示にする
  194.   HideTestIndicators(true);
  195.  
  196.   CurTime = MainTime();
  197.   CurPmdInt = CurSclpInt = TimeTick = CancelTime = StartTime = UserTime = BaseTime();
  198.  
  199.   Lots = BaseLots ; PrevBid = PmdPrevBid = Bid ; PrevAsk = PmdPrevAsk = Ask ;
  200.   if(Lots<MinLots) Lots = MinLots ;
  201.   if(Lots>MaxLots) Lots = MaxLots ;
  202.  
  203.   DeleteBorderLines() ;
  204.  
  205.   DrawBorderLine(OP_BUY);
  206.   DrawBorderLine(OP_SELL);
  207.  
  208.   BuyTrailLined = ObjectFind(BUYTRAIL_NAME)>=0 ;
  209.   SellTrailLined = ObjectFind(SELLTRAIL_NAME)>=0 ;
  210.  
  211.   BuyTLEntried=SellTLEntried=EntryTLPos;
  212.   BuyFastMAEntried=SellFastMAEntried=EntryFastMAPos;
  213.   BuyMediumMAEntried=SellMediumMAEntried=EntryMediumMAPos;
  214.  
  215.   // LossPrices 値読込
  216.   if(!GlobalVariableGet(LOSSPRICES_NAME,LossPrices))
  217.     LossPrices = 0.0;
  218.  
  219.   STATUS buyStatus, sellStatus ;
  220.   CheckStatus(OP_BUY,MAGICMA,buyStatus);
  221.   CheckStatus(OP_SELL,MAGICMA,sellStatus);
  222.   // done : borderPrice を medianPrice に置換する
  223.   if(buyStatus.Positions>0) {
  224.     double totalLots = buyStatus.TotalLots ;
  225.     double totalPrice = buyStatus.TotalPrices ;
  226.     double borderPrice = buyStatus.BorderPrice ;
  227.     double offsetPrice = Offsetting?-sellStatus.CurrentPrices:0;
  228.     bool offs = Offsetting && offsetPrice>0 ;
  229.     if(offs) {
  230.       double medianPrice = buyStatus.MedianBorderPrice(sellStatus,LossPrices) ;
  231.       if(medianPrice!=0.0) borderPrice = medianPrice;
  232.       else borderPrice = (totalPrice+offsetPrice)/totalLots ;
  233.     }
  234.     //double profitPrice = buyStatus.ProfitPrice(borderPrice) ;
  235.     BuyKeepTimer = CheckOverPriceTime(OP_BUY,borderPrice,buyStatus.MinOpenTime) ;
  236.     if(ProfitKeepTL!=0&&BuyKeepTimer>=ProfitKeepTL) BuyTLEntried = false ;
  237.     BuyMaxPrice = buyStatus.MaxPrice ;
  238.     double price;
  239.     if(GlobalVariableGet(BUYMAXPRICE_NAME,price)) {
  240.       if(price>BuyMaxPrice) {
  241.         BuyMaxPrice = price ;
  242.       }
  243.       GlobalVariableDel(BUYMAXPRICE_NAME);
  244.     }
  245.   }
  246.   if(sellStatus.Positions>0) {
  247.     double totalLots = sellStatus.TotalLots ;
  248.     double totalPrice = sellStatus.TotalPrices ;
  249.     double borderPrice = sellStatus.BorderPrice; ;
  250.     double offsetPrice = Offsetting?-buyStatus.CurrentPrices:0;
  251.     bool offs = Offsetting && offsetPrice>0 ;
  252.     if(offs) {
  253.       double medianPrice = sellStatus.MedianBorderPrice(buyStatus,LossPrices) ;
  254.       if(medianPrice!=0.0) borderPrice = medianPrice;
  255.       else borderPrice = (totalPrice-offsetPrice)/totalLots ;
  256.     }
  257.     //double profitPrice = sellStatus.ProfitPrice(borderPrice) ;
  258.     SellKeepTimer = CheckOverPriceTime(OP_SELL,borderPrice,sellStatus.MinOpenTime) ;
  259.     if(ProfitKeepTL!=0&&SellKeepTimer>=ProfitKeepTL) SellTLEntried = false ;
  260.     SellMinPrice = sellStatus.MinPrice ;
  261.     double price;
  262.     if(GlobalVariableGet(SELLMINPRICE_NAME,price)) {
  263.       if(price<SellMinPrice) {
  264.         SellMinPrice = price ;
  265.       }
  266.       GlobalVariableDel(SELLMINPRICE_NAME);
  267.     }
  268.   }
  269.  
  270.   // エントリできるポジションの確認
  271.   switch(ActivePositions) {
  272.     case POSI_STOP:                  // Stop
  273.       PositionFlag = 0 ;
  274.       break;
  275.     case POSI_ONLY_LONG:             // Only Long
  276.       PositionFlag = FLAG_BUY ;
  277.       break;
  278.     case POSI_ONLY_SHORT:            // Only Short
  279.       PositionFlag = FLAG_SELL ;
  280.       break;
  281.     case POSI_HALF_LONG_AND_SHORT:   // Long & Short (Half Duplex)
  282.       PositionFlag = FLAG_BUY | FLAG_SELL ;
  283.       break;
  284.     case POSI_FULL_LONG_AND_SHORT:   // Long & Short (Full Duplex)
  285.       PositionFlag = FLAG_BUY | FLAG_SELL | FLAG_DUPLEX ;
  286.       break;
  287.   }
  288.  
  289.   //DEBUG INFO
  290.   if(DBGMODE) {
  291.     ObjectCreate(DBGINFO_NAME, OBJ_LABEL, 0, 0, 0);
  292.     ObjectSet(DBGINFO_NAME, OBJPROP_XDISTANCE, 10);
  293.     ObjectSet(DBGINFO_NAME, OBJPROP_YDISTANCE, 15);
  294.     ObjectSet(DBGINFO_NAME, OBJPROP_CORNER, 3);
  295.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, "DEBUG INFO");
  296.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_FONT, "Verdana");
  297.     ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_FONTSIZE, 8);
  298.     ObjectSetInteger(0, DBGINFO_NAME, OBJPROP_COLOR, clrAquamarine);
  299.   }
  300.  
  301.   //金額表示
  302.   if(ShowAmount) {
  303.     ObjectCreate(AMOUNT_NAME, OBJ_LABEL, 0, 0, 0);
  304.     ObjectSet(AMOUNT_NAME, OBJPROP_XDISTANCE, 20);
  305.     ObjectSet(AMOUNT_NAME, OBJPROP_YDISTANCE, 35);
  306.     ObjectSet(AMOUNT_NAME, OBJPROP_CORNER, 3);
  307.     ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, "0-");
  308.     ObjectSetString(0, AMOUNT_NAME, OBJPROP_FONT, "Verdana");
  309.     ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_FONTSIZE, 15);
  310.     ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
  311.   }
  312.  
  313.   //ユーザーエントリ用ボタン
  314.   if(ShowUserEntry) {
  315.  
  316.     //SELLボタン
  317.     ObjectCreate(SELLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  318.     ObjectSet(SELLBTN_NAME, OBJPROP_XDISTANCE, 10);
  319.     ObjectSet(SELLBTN_NAME, OBJPROP_YDISTANCE, 20);
  320.     ObjectSet(SELLBTN_NAME, OBJPROP_XSIZE, 58);
  321.     ObjectSet(SELLBTN_NAME, OBJPROP_YSIZE, 32);
  322.     ObjectSet(SELLBTN_NAME, OBJPROP_CORNER, 0);
  323.     ObjectSet(SELLBTN_NAME, OBJPROP_FONTSIZE, 12);
  324.     ObjectSet(SELLBTN_NAME, OBJPROP_COLOR, White);
  325.     ObjectSet(SELLBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
  326.     ObjectSetString(0, SELLBTN_NAME, OBJPROP_TEXT, "SELL");
  327.     ObjectSetString(0, SELLBTN_NAME, OBJPROP_FONT, "Verdana");
  328.  
  329.     //BUYボタン
  330.     ObjectCreate(BUYBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  331.     ObjectSet(BUYBTN_NAME, OBJPROP_XDISTANCE, 70);
  332.     ObjectSet(BUYBTN_NAME, OBJPROP_YDISTANCE, 20);
  333.     ObjectSet(BUYBTN_NAME, OBJPROP_XSIZE, 58);
  334.     ObjectSet(BUYBTN_NAME, OBJPROP_YSIZE, 32);
  335.     ObjectSet(BUYBTN_NAME, OBJPROP_CORNER, 0);
  336.     ObjectSet(BUYBTN_NAME, OBJPROP_FONTSIZE, 12);
  337.     ObjectSet(BUYBTN_NAME, OBJPROP_COLOR, White);
  338.     ObjectSet(BUYBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
  339.     ObjectSetString(0, BUYBTN_NAME, OBJPROP_TEXT, "BUY");
  340.     ObjectSetString(0, BUYBTN_NAME, OBJPROP_FONT, "Verdana");
  341.  
  342.   }
  343.  
  344.   int btn_ofs_x = 0 ;
  345.   const int btn_distance = 102 ;
  346.  
  347.   //全決済ボタン
  348.   if(ShowCloseAll) {
  349.     ObjectCreate(CLOSEALLBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  350.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  351.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YDISTANCE, 35);
  352.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_XSIZE, 100);
  353.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_YSIZE, 25);
  354.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_CORNER, 2);
  355.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_FONTSIZE, 10);
  356.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_COLOR, White);
  357.     ObjectSet(CLOSEALLBTN_NAME, OBJPROP_BGCOLOR, /*clrDarkGreen*/clrDarkSlateGray);
  358.     ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_TEXT, "CLOSE ALL");
  359.     ObjectSetString(0, CLOSEALLBTN_NAME, OBJPROP_FONT, "Verdana");
  360.     btn_ofs_x += btn_distance ;
  361.   }
  362.  
  363.   //LONG決済ボタン
  364.   if(ShowCloseLong) {
  365.     ObjectCreate(CLOSELONGBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  366.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  367.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YDISTANCE, 35);
  368.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_XSIZE, 100);
  369.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_YSIZE, 25);
  370.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_CORNER, 2);
  371.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_FONTSIZE, 10);
  372.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_COLOR, White);
  373.     ObjectSet(CLOSELONGBTN_NAME, OBJPROP_BGCOLOR, clrRoyalBlue);
  374.     ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_TEXT, "CLOSE LONG");
  375.     ObjectSetString(0, CLOSELONGBTN_NAME, OBJPROP_FONT, "Verdana");
  376.     btn_ofs_x += btn_distance ;
  377.   }
  378.  
  379.   //SHORT決済ボタン
  380.   if(ShowCloseShort) {
  381.     ObjectCreate(CLOSESHORTBTN_NAME, OBJ_BUTTON, 0, 0, 0);
  382.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XDISTANCE, 10 + btn_ofs_x );
  383.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YDISTANCE, 35);
  384.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_XSIZE, 100);
  385.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_YSIZE, 25);
  386.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_CORNER, 2);
  387.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_FONTSIZE, 10);
  388.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_COLOR, White);
  389.     ObjectSet(CLOSESHORTBTN_NAME, OBJPROP_BGCOLOR, clrFireBrick);
  390.     ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_TEXT, "CLOSE SHORT");
  391.     ObjectSetString(0, CLOSESHORTBTN_NAME, OBJPROP_FONT, "Verdana");
  392.     btn_ofs_x += btn_distance ;
  393.   }
  394.  
  395.   //ユーザーエントリをリセット
  396.   UserEntry=0;
  397.  
  398.   return(INIT_SUCCEEDED);
  399. }
  400. //---------------------------------------------------------------------------
  401. void OnDeinit(const int reason)
  402. {
  403.   int flag = AlreadyOrdered(FLAG_BUY|FLAG_SELL,MAGICMA);
  404.   if(flag!=0) {
  405.     if((flag&FLAG_BUY)!=0) GlobalVariableSet(BUYMAXPRICE_NAME,BuyMaxPrice);
  406.     if((flag&FLAG_SELL)!=0) GlobalVariableSet(SELLMINPRICE_NAME,SellMinPrice);
  407.   }
  408.   if(ShowCloseShort) ObjectDelete(CLOSESHORTBTN_NAME) ;
  409.   if(ShowCloseLong) ObjectDelete(CLOSELONGBTN_NAME) ;
  410.   if(ShowCloseAll) ObjectDelete(CLOSEALLBTN_NAME) ;
  411.   if(ShowUserEntry) {
  412.     ObjectDelete(BUYBTN_NAME) ;
  413.     ObjectDelete(SELLBTN_NAME) ;
  414.   }
  415.   if(OffTimeVisible) {
  416.     ObjectDelete(OFFTIME_NAME) ;
  417.     OffTimeVisible=false ;
  418.   }
  419.   if(ShowAmount) {
  420.     ObjectDelete(AMOUNT_NAME) ;
  421.   }
  422.   if(DBGMODE) {
  423.     ObjectDelete(DBGINFO_NAME) ;
  424.   }
  425.   DeleteBorderLines() ;
  426. }
  427. //---------------------------------------------------------------------------
  428. void OnTick()
  429. {
  430.   datetime nextTime = MainTime() ;
  431.   bool nextTimed = nextTime != CurTime ;
  432.   CurTime = nextTime ;
  433.  
  434.   datetime nextTick = BaseTime() ;
  435.   bool nextTicked = nextTick != TimeTick ;
  436.   TimeTick = nextTick;
  437.  
  438.   // タイムコントロールチェック
  439.   CheckTimeControl(nextTicked);
  440.  
  441.   // 動作チェック
  442.   CheckBehavior(nextTimed);
  443.  
  444.   double atr14 = iATR(NULL,0,14,0) ;
  445.   double spread = Ask-Bid ;
  446.  
  447.   // デバッグ欄表示のサンプル
  448.   if(DBGMODE) {
  449.     DBGOUT(
  450.       // ATR in points
  451.       StringFormat("ATR(14): %.3f",atr14/Point) + " | " +
  452.       // SPREAD in points
  453.       StringFormat("SPREAD: %g",spread/Point) + " | " +
  454.       // 現在の値幅の変動倍率(ATR/SPREAD)
  455.       StringFormat("ATR(14)/SPREAD: %.3f",atr14/(spread<=0?1:spread))
  456.     );
  457.   }
  458.  
  459.   // エントリー処理
  460.   if(IsExpertEnabled()&&IsTradeAllowed()) {
  461.  
  462.     int busy = AlreadyOrdered(FLAG_BUY|FLAG_SELL,MAGICMA) ;
  463.  
  464.     if(ReferSlowMA) { // Slow MA の位置によりビジー状態を設定する
  465.       double SlowMA0 = iMA(NULL, MainTimeFrame, SlowMAPeriod, MAShift, MAMode, MAPriceType, 0);
  466.       double HalfSpread = (Ask-Bid)/2.0;
  467.       SlowMA0+=HalfSpread ;
  468.       if(Ask<SlowMA0) busy |= FLAG_BUY ;
  469.       if(Bid>SlowMA0) busy |= FLAG_SELL ;
  470.     }
  471.  
  472.     /*
  473.     if(RSIPredict) { // RSI による売買制限
  474.       if(RSIUpBuyLimit<RSI0||RSIDownBuyLimit>RSI0) busy |= FLAG_BUY ;
  475.       if(RSIUpSellLimit<RSI0||RSIDownSellLimit>RSI0) busy |= FLAG_SELL ;
  476.     }
  477.     */
  478.  
  479.     // ユーザーの注文
  480.     if(UserEntry) {
  481.  
  482.       // ユーザーのエントリを確認
  483.       if(TimeTick-UserTime<60) {  // 発行されてから60秒以内の注文
  484.  
  485.         int user = UserEntry ;
  486.  
  487.         // 注文
  488.         if(user&&!AlreadyOrdered(user,MAGICMA)) {
  489.  
  490.           int entry = user == FLAG_BUY ? OP_BUY : OP_SELL ;
  491.           EntryPosition("USER", entry, Lots);
  492.           busy |= user ;
  493.         }
  494.  
  495.       }
  496.  
  497.       UserEntry=0;
  498.     }
  499.  
  500.     // MARK: 自動注文
  501.  
  502.     do {
  503.  
  504.       // 自動注文 開始時間調整
  505.       if(StartTime>TimeTick||CancelTime>TimeTick)
  506.         break ;
  507.  
  508.       // 自動注文 MA RSI Cross Detector
  509.       if(MARSIXDetector)
  510.         EAEntryPosition("MARSIX", CheckDetectorMARSIX(), busy);
  511.  
  512.       // 自動注文 2MM Detector
  513.       if(MMX2Detector && nextTimed)
  514.         EAEntryPosition("2MM", CheckDetectorMMX2(1),busy) ;
  515.  
  516.       // 自動注文 COBRA Detector
  517.       if(COBRADetector && nextTimed)
  518.         EAEntryPosition("COBRA", CheckDetectorCOBRA(1),busy) ;
  519.  
  520.       // 自動注文 GXRSI Detector
  521.       if(GXRSIDetector && nextTimed)
  522.         EAEntryPosition("GXRSI", CheckDetectorGXRSI(1),busy) ;
  523.  
  524.     }while(0);
  525.  
  526.   }else {
  527.  
  528.     if(StartTime-TimeTick<10)
  529.       StartTime = TimeTick+10 ;
  530.  
  531.   }
  532.  
  533.   if(PmdTiming) {
  534.     PmdPrevBid = (PmdPrevBid+Bid)/2.0 ; PmdPrevAsk = (PmdPrevAsk+Ask)/2.0 ;
  535.   }
  536.   PrevBid = Bid ; PrevAsk = Ask ;
  537. }
  538. //---------------------------------------------------------------------------
  539. void OnChartEvent(
  540.   const int id,
  541.   const long &lparam,
  542.   const double &dparam,
  543.   const string &sparam
  544.  )
  545. {
  546.   if( ( sparam == CLOSEALLBTN_NAME ||
  547.         sparam == CLOSELONGBTN_NAME ||
  548.         sparam == CLOSESHORTBTN_NAME ) && id==CHARTEVENT_OBJECT_CLICK) {
  549.     int orderFlag = 0 ;
  550.     if(sparam == CLOSEALLBTN_NAME) orderFlag = FLAG_SELL | FLAG_BUY ;
  551.     else if(sparam == CLOSELONGBTN_NAME) orderFlag = FLAG_BUY ;
  552.     else if(sparam == CLOSESHORTBTN_NAME) orderFlag = FLAG_SELL ;
  553.     CheckoutOrderAll(orderFlag);
  554.     Sleep(100);
  555.     ObjectSet(sparam, OBJPROP_STATE, False);
  556.     // 60秒エントリーを停止する
  557.     CancelTime = TimeTick + 60 ;
  558.   }
  559.   if(sparam == SELLBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  560.     { UserEntry = FLAG_SELL ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
  561.     Sleep(100);
  562.     ObjectSet(SELLBTN_NAME, OBJPROP_STATE, False);
  563.   }
  564.   if(sparam == BUYBTN_NAME && id==CHARTEVENT_OBJECT_CLICK) {
  565.     { UserEntry = FLAG_BUY ; CancelTime = UserTime = TimeTick ; CancelTime+=60 ; }
  566.     Sleep(100);
  567.     ObjectSet(BUYBTN_NAME, OBJPROP_STATE, False);
  568.   }
  569. }
  570. //---------------------------------------------------------------------------
  571. //DBGOUT
  572. void DBGOUT(string text)
  573. {
  574.   if(DBGMODE) {
  575.     ObjectSetString(0, DBGINFO_NAME, OBJPROP_TEXT, text);
  576.   }
  577. }
  578. //---------------------------------------------------------------------------
  579. //タイムコントロールチェック
  580. void CheckTimeControl(bool nextTicked)
  581. {
  582.   if(!TimeControl) {
  583.     if(OffTimeVisible) {
  584.       ObjectDelete(OFFTIME_NAME);
  585.       OffTimeVisible = false ;
  586.     }
  587.     return ;
  588.   }
  589.   if(!nextTicked) return ;
  590.  
  591.   datetime timStart = StringToTime(TimeStart);
  592.   datetime timEnd   = StringToTime(TimeEnd);
  593.  
  594.   MqlDateTime mqlTick, mqlStart, mqlEnd ;
  595.   TimeToStruct(TimeTick, mqlTick);
  596.   TimeToStruct(timStart, mqlStart);
  597.   TimeToStruct(timEnd, mqlEnd);
  598.  
  599.   // 活動時間帯のチェック
  600.   int ct = mqlTick.hour*60 + mqlTick.min ;
  601.   int st = mqlStart.hour*60 + mqlStart.min ;
  602.   int et = mqlEnd.hour*60 + mqlEnd.min ;
  603.   if(et<=st) {
  604.     if(st<=ct) et=24*60;
  605.     if(ct<=et) st=0;
  606.   }
  607.   bool activeTime = st <= ct && ct <= et ;
  608.  
  609.   bool isActivated = StartTime<TimeTick ;
  610.  
  611.   // 現在活動時間帯
  612.   if(activeTime) {
  613.     if(!isActivated)
  614.       StartTime = TimeTick ; // 現在時間を開始時間切り上げて完了
  615.     if(OffTimeVisible) {
  616.       ObjectDelete(OFFTIME_NAME);
  617.       OffTimeVisible = false ;
  618.     }
  619.     return ;
  620.   }
  621.  
  622.   // 活動時間を次の時間にセットする
  623.   MqlDateTime mqlNextStart = mqlTick ;
  624.   mqlNextStart.hour = mqlStart.hour ;
  625.   mqlNextStart.min = mqlStart.min ;
  626.   mqlNextStart.sec = 0 ;
  627.   datetime timNextStart = StructToTime(mqlNextStart) ;
  628.   while(timNextStart<TimeTick)  timNextStart += 24*60*60 ;
  629.   StartTime = timNextStart ;
  630.  
  631.   // 次の開始までの秒数
  632.   datetime timOff = StartTime - TimeTick ;
  633.   if(!OffTimeVisible) {
  634.     // OFF TIME テキストを表示
  635.     ObjectCreate(OFFTIME_NAME, OBJ_LABEL, 0, 0, 0);
  636.     ObjectSet(OFFTIME_NAME, OBJPROP_XDISTANCE, 10);
  637.     ObjectSet(OFFTIME_NAME, OBJPROP_YDISTANCE, 25);
  638.     ObjectSet(OFFTIME_NAME, OBJPROP_CORNER, 1);
  639.     ObjectSetString(0, OFFTIME_NAME, OBJPROP_TEXT, "OFF TIME");
  640.     ObjectSetString(0, OFFTIME_NAME, OBJPROP_FONT, "Verdana");
  641.     ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_FONTSIZE, 8);
  642.     ObjectSetInteger(0, OFFTIME_NAME, OBJPROP_COLOR, ClrTimeControl);
  643.     OffTimeVisible = true ;
  644.   }
  645.  
  646.   int orderFlag = AlreadyOrdered(FLAG_SELL|FLAG_BUY,MAGICMA);
  647.  
  648.   switch(TimeAction) {
  649.     case TIMEACT_NONE:
  650.       // None
  651.       break;
  652.     case TIMEACT_FORCE_CLOSE_ALL:
  653.       // Force Close All positions
  654.       if(orderFlag!=0)
  655.         CheckoutOrderAll(orderFlag);
  656.       break;
  657.     case TIMEACT_FORCE_CLOSE_LONG:
  658.       // Force Close Long positions
  659.       if((orderFlag&FLAG_BUY)!=0)
  660.         CheckoutOrderAll(FLAG_BUY);
  661.       break;
  662.     case TIMEACT_FORCE_CLOSE_SHORT:
  663.       // Force Close Short positions
  664.       if((orderFlag&FLAG_SELL)!=0)
  665.         CheckoutOrderAll(FLAG_SELL);
  666.       break;
  667.     case TIMEACT_SOFT_CLOSE_ALL:
  668.       // Close All positions if profits are Positive
  669.       if(orderFlag!=0) {
  670.         STATUS status_long, status_short;
  671.         CheckStatus(OP_BUY,MAGICMA,status_long);
  672.         CheckStatus(OP_SELL,MAGICMA,status_short);
  673.         double total = status_long.GrossProfit+status_short.GrossProfit ;
  674.         if(total>0) {
  675.           CheckoutOrderAll(orderFlag);
  676.         }
  677.       }
  678.       break;
  679.     case TIMEACT_SOFT_CLOSE_LONG:
  680.       // Close Long positions if profits are Positive
  681.       if((orderFlag&FLAG_BUY)!=0) {
  682.         STATUS status_long;
  683.         CheckStatus(OP_BUY,MAGICMA,status_long);
  684.         double total=status_long.GrossProfit;
  685.         if(total>0) {
  686.           CheckoutOrderAll(FLAG_BUY);
  687.         }
  688.       }
  689.       break;
  690.     case TIMEACT_SOFT_CLOSE_SHORT:
  691.       // Close Short positions if profits are Positive
  692.       if((orderFlag&FLAG_SELL)!=0) {
  693.         STATUS status_short;
  694.         CheckStatus(OP_SELL,MAGICMA,status_short);
  695.         double total=status_short.GrossProfit;
  696.         if(total>0) {
  697.           CheckoutOrderAll(FLAG_SELL);
  698.         }
  699.       }
  700.       break;
  701.   }
  702. }
  703. //---------------------------------------------------------------------------
  704. //メインタイムを返す
  705. datetime MainTime(int shift=0)
  706. {
  707.   return iTime(Symbol(), MainTimeFrame, shift);
  708. }
  709. //---------------------------------------------------------------------------
  710. //タイムコントロールの基軸時間を返す
  711. datetime BaseTime()
  712. {
  713.   switch(TimeBase) {
  714.     case TIMEBASE_GMT:               // Greenwich Mean Time (GMT)
  715.       return TimeGMT();
  716.     case TIMEBASE_LOCAL:             // Local Time
  717.       return TimeLocal();
  718.     case TIMEBASE_SERVER:            // Server Time
  719.       return TimeCurrent();
  720.   }
  721.   return 0;
  722. }
  723. //---------------------------------------------------------------------------
  724. //price超えの時間経過を調べる
  725. int CheckOverPriceTime(int type, double border, datetime minTime)
  726. {
  727.   double spread = Ask-Bid ;
  728.   bool buy = false ;
  729.   switch(type) {
  730.     case OP_BUY: buy=true; break;
  731.     case OP_SELL: buy=false; break;
  732.     default: return 0 ;
  733.   }
  734.   int numBars = iBars(Symbol(),MainTimeFrame);
  735.   int times=0;
  736.   for(int i=0;i<numBars;i++) {
  737.     if(MainTime(i)<=minTime) break;
  738.     if(buy?
  739.         border>=iOpen(Symbol(),MainTimeFrame,i):
  740.         border+spread<=iOpen(Symbol(),MainTimeFrame,i)) break;
  741.     times++;
  742.   }
  743.   return times;
  744. }
  745. //---------------------------------------------------------------------------
  746. //金額表示の更新
  747. void UpdateAmount(double amount, int positions)
  748. {
  749.   if(ShowAmount) {
  750.     if(positions>0) {
  751.       string s = DoubleToAmount(amount,AmountDig) ;
  752.       if(amount>0) s = "+" + s ;
  753.       ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s);
  754.       if(amount<0)
  755.         ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_NEGA);
  756.       else
  757.         ObjectSetInteger(0, AMOUNT_NAME, OBJPROP_COLOR, AMOUNT_CLR_POSI);
  758.     }else {
  759.       string s = ObjectGetString(0, AMOUNT_NAME, OBJPROP_TEXT);
  760.       int ln=StringLen(s);
  761.       if(ln>0) {
  762.         if(s[ln-1]!='-')
  763.           ObjectSetString(0, AMOUNT_NAME, OBJPROP_TEXT, s+"-");
  764.       }
  765.     }
  766.   }
  767. }
  768. //---------------------------------------------------------------------------
  769. //状態チェック
  770. //-----
  771. struct ORDER_STATUS {
  772.   int Ticket;
  773.   double Price;
  774.   double Stoploss;
  775.   double Takeprofit;
  776.   double Lots;
  777.   double Profit;
  778.   datetime OpenTime;
  779.   string Comment;
  780.   //-----
  781.   ORDER_STATUS() {
  782.     Ticket = -1 ;
  783.     Price = Stoploss = Takeprofit = Lots = Profit = 0.0 ;
  784.     OpenTime = 0 ;
  785.     Comment = "" ;
  786.   }
  787.   ORDER_STATUS(
  788.       int Ticket_,
  789.       double Price_,
  790.       double Stoploss_,
  791.       double Takeprofit_,
  792.       double Lots_,
  793.       double Profit_,
  794.       datetime OpenTime_,
  795.       string Comment_ ) {
  796.     Ticket = Ticket_;
  797.     Price = Price_;
  798.     Stoploss = Stoploss_;
  799.     Takeprofit = Takeprofit_;
  800.     Lots = Lots_;
  801.     Profit = Profit_;
  802.     OpenTime = OpenTime_;
  803.     Comment = Comment_;
  804.   }
  805.   bool operator <(const ORDER_STATUS &rhs) const {
  806.     return Price<rhs.Price;
  807.   }
  808. };
  809. //-----
  810. struct STATUS {
  811.   int Type, Magic;
  812.   int Positions, PyramidPositions, AveragePositions;
  813.   double MinPrice, MaxPrice, BorderPrice;
  814.   double MinPriceLots, MaxPriceLots;
  815.   double MinPriceProfit, MaxPriceProfit;
  816.   double MinPriceStoploss, MaxPriceStoploss;
  817.   int MinPriceTicket, MaxPriceTicket;
  818.   double MinStoploss, MaxStoploss;
  819.   double MinTakeprofit, MaxTakeprofit;
  820.   double MinLots, MaxLots;
  821.   datetime MinOpenTime, MaxOpenTime;
  822.   double PyramidMinLots, PyramidMaxLots;
  823.   double AverageMinLots, AverageMaxLots;
  824.   double TotalPrices, TotalLots;
  825.   double CurrentPrices, MedianPrices;
  826.   double GrossProfit;
  827.   double PositiveProfit;
  828.   CArrayObj *Orders;
  829.   STATUS() {
  830.     Orders = new CArrayObj();
  831.   }
  832.   ~STATUS() {
  833.     delete Orders;
  834.   }
  835.   void Check(int type, int magic) {
  836.     Type=type;
  837.     Magic=magic;
  838.     Positions = 0 ;
  839.     PyramidPositions = 0 ;
  840.     AveragePositions = 0 ;
  841.     MinPrice = DBL_MAX ;
  842.     MaxPrice = 0.0 ;
  843.     MinPriceLots = 0.0 ;
  844.     MaxPriceLots = 0.0 ;
  845.     MinPriceProfit = 0.0 ;
  846.     MaxPriceProfit = 0.0 ;
  847.     MinPriceStoploss = 0.0 ;
  848.     MaxPriceStoploss = 0.0 ;
  849.     MinPriceTicket = 0 ;
  850.     MaxPriceTicket = 0 ;
  851.     MinStoploss = DBL_MAX ;
  852.     MaxStoploss = 0.0 ;
  853.     MinTakeprofit = DBL_MAX ;
  854.     MaxTakeprofit = 0.0 ;
  855.     MinLots = DBL_MAX ;
  856.     MaxLots = 0.0 ;
  857.     MinOpenTime = TimeCurrent() ;
  858.     MaxOpenTime = 0 ;
  859.     PyramidMinLots = DBL_MAX ;
  860.     PyramidMaxLots = 0.0 ;
  861.     AverageMinLots = DBL_MAX ;
  862.     AverageMaxLots = 0.0 ;
  863.     BorderPrice = 0.0 ;
  864.     GrossProfit = 0.0 ;
  865.     PositiveProfit = 0.0 ;
  866.     CurrentPrices = 0.0 ;
  867.     MedianPrices = 0.0 ;
  868.     Orders.Clear();
  869.     double halfSpread = (Ask-Bid)/2.0;
  870.     double totalPrice=0, totalLots=0 ;
  871.     for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
  872.       if( OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol() ) {
  873.         if(magic==OrderMagicNumber()) {
  874.           if(type==OrderType()) {
  875.             int orderTicket = OrderTicket() ;
  876.             double orderPrice = OrderOpenPrice();
  877.             double orderStoploss = OrderStopLoss();
  878.             double orderTakeprofit = OrderTakeProfit();
  879.             double orderLots = OrderLots();
  880.             double orderProfit = OrderProfit() ;
  881.             datetime orderOpenTime = OrderOpenTime() ;
  882.             string orderComment = OrderComment();
  883.             AddToArray(Orders, ORDER_STATUS(
  884.               orderTicket,
  885.               orderPrice,
  886.               orderStoploss,
  887.               orderTakeprofit,
  888.               orderLots,
  889.               orderProfit,
  890.               orderOpenTime,
  891.               orderComment )
  892.             );
  893.             GrossProfit += orderProfit;
  894.             if(orderProfit>0.0)
  895.               PositiveProfit += orderProfit;
  896.             if(orderPrice<MinPrice) {
  897.               MinPrice = orderPrice ;
  898.               MinPriceLots = orderLots ;
  899.               MinPriceProfit = orderProfit ;
  900.               MinPriceStoploss = orderStoploss ;
  901.               MinPriceTicket = orderTicket ;
  902.             }
  903.             if(orderPrice>MaxPrice) {
  904.               MaxPrice = orderPrice ;
  905.               MaxPriceLots = orderLots ;
  906.               MaxPriceProfit = orderProfit ;
  907.               MaxPriceStoploss = orderStoploss ;
  908.               MaxPriceTicket = orderTicket ;
  909.             }
  910.             if(orderStoploss<MinStoploss) MinStoploss = orderStoploss;
  911.             if(orderStoploss>MaxStoploss) MaxStoploss = orderStoploss;
  912.             if(orderTakeprofit<MinTakeprofit) MinTakeprofit = orderTakeprofit;
  913.             if(orderTakeprofit>MaxTakeprofit) MaxTakeprofit = orderTakeprofit;
  914.             if(orderLots<MinLots) MinLots = orderLots;
  915.             if(orderLots>MaxLots) MaxLots = orderLots;
  916.             totalPrice += orderPrice*orderLots ;
  917.             totalLots += orderLots;
  918.             if(type==OP_BUY) {
  919.               CurrentPrices += (Bid - orderPrice) * orderLots ;
  920.               MedianPrices += (orderPrice + halfSpread) * orderLots ;
  921.             }
  922.             else if(type==OP_SELL) {
  923.               CurrentPrices += (orderPrice - Ask) * orderLots ;
  924.               MedianPrices += (orderPrice - halfSpread) * orderLots ;
  925.             }
  926.             if(MaxOpenTime<orderOpenTime) MaxOpenTime=orderOpenTime;
  927.             if(MinOpenTime>orderOpenTime) MinOpenTime=orderOpenTime;
  928.             if(StringFind(orderComment,"PRMD")>=0) {
  929.               if(orderLots>PyramidMaxLots)
  930.                 PyramidMaxLots = orderLots ;
  931.               if(orderLots<PyramidMinLots)
  932.                 PyramidMinLots = orderLots ;
  933.               PyramidPositions++;
  934.             }
  935.             if(StringFind(orderComment,"AVRG")>=0) {
  936.               if(orderLots>AverageMaxLots)
  937.                 AverageMaxLots = orderLots ;
  938.               if(orderLots<AverageMinLots)
  939.                 AverageMinLots = orderLots ;
  940.               AveragePositions++;
  941.             }
  942.             Positions++;
  943.           }
  944.         }
  945.       }
  946.     }
  947.     Orders.Sort(ARRAY_SORT_ASCEND);
  948.     if(!PyramidPositions) {
  949.       PyramidMinLots = Lots ;
  950.       PyramidMaxLots = Lots ;
  951.     }
  952.     if(!AveragePositions) {
  953.       AverageMinLots = Lots ;
  954.       AverageMaxLots = Lots ;
  955.     }
  956.     if(totalLots>0) {
  957.       BorderPrice = totalPrice / totalLots ;
  958.     }
  959.     TotalPrices = totalPrice ;
  960.     TotalLots = totalLots ;
  961.   }
  962.   double ProfitPrice(double borderPrice=0.0) const {
  963.     if(borderPrice==0.0) borderPrice = BorderPrice;
  964.     if(borderPrice>0.0) {
  965.       //double stride = PyramidingStride * Point ;
  966.       switch(Type) {
  967.         case OP_BUY: {
  968.           double bar = MathMax(MaxPrice,BuyMaxPrice)-borderPrice ;
  969.           if(bar>0.0) {
  970.             return bar * (ProfitRatePer / 100.0) + borderPrice ;
  971.           }
  972.           break;
  973.         }
  974.         case OP_SELL: {
  975.           double bar = MathMin(MinPrice,SellMinPrice)-borderPrice ;
  976.           if(bar<0.0) {
  977.             return bar * (ProfitRatePer / 100.0) + borderPrice ;
  978.           }
  979.           break;
  980.         }
  981.       }
  982.     }
  983.     return borderPrice ;
  984.   }
  985.   double MedianBorderPrice(const STATUS &revStatus, double lossPrices=0.0) const
  986.   {
  987.     double medianLots = Type==OP_BUY ? TotalLots : -TotalLots ;
  988.     medianLots += revStatus.Type==OP_BUY ? revStatus.TotalLots: -revStatus.TotalLots ;
  989.     if(Type==OP_BUY?medianLots>0.0:medianLots<0.0) {
  990.       double medianPrices = Type==OP_BUY ? MedianPrices-lossPrices : -MedianPrices+lossPrices ;
  991.       medianPrices += revStatus.Type==OP_BUY ? revStatus.MedianPrices: -revStatus.MedianPrices ;
  992.       double medianBorder = medianPrices/medianLots ;
  993.       switch(Type) {
  994.         case OP_BUY:
  995.             medianBorder -= (Ask-Bid)/2.0;
  996.             break;
  997.         case OP_SELL:
  998.             medianBorder += (Ask-Bid)/2.0;
  999.             break;
  1000.       }
  1001.       return medianBorder ;
  1002.     }
  1003.     return 0.0;
  1004.   }
  1005. };
  1006. //-----
  1007. int CheckStatus(int type, int magic, STATUS &status)
  1008. {
  1009.   status.Check(type,magic);
  1010.   return status.Positions;
  1011. }
  1012. //---------------------------------------------------------------------------
  1013. //動作チェック
  1014. void CheckBehavior(bool nextTimed)
  1015. {
  1016.   //最高価格/最低価格の更新
  1017.   bool lineUpdTiming = nextTimed ;
  1018.   if(Bid>BuyMaxPrice) {
  1019.     BuyMaxPrice = Bid ;
  1020.     BuyLosscutTimer = 0 ;
  1021.     lineUpdTiming = true ;
  1022.   }else if(nextTimed) {
  1023.     double o = iOpen(Symbol(),MainTimeFrame,1);
  1024.     double c = iClose(Symbol(),MainTimeFrame,1);
  1025.     if(o>c) BuyLosscutTimer++;
  1026.   }
  1027.   if(Ask<SellMinPrice) {
  1028.     SellMinPrice = Ask ;
  1029.     SellLosscutTimer = 0 ;
  1030.     lineUpdTiming = true ;
  1031.   }else if(nextTimed) {
  1032.     double o = iOpen(Symbol(),MainTimeFrame,1);
  1033.     double c = iClose(Symbol(),MainTimeFrame,1);
  1034.     if(o<c) SellLosscutTimer++;
  1035.   }
  1036.  
  1037.   // 全体のステータスを取得
  1038.   STATUS BuyWholeStatus, SellWholeStatus ;
  1039.   CheckStatus(OP_BUY, MAGICMA, BuyWholeStatus);
  1040.   CheckStatus(OP_SELL, MAGICMA, SellWholeStatus);
  1041.  
  1042.   // 損益の初期化
  1043.   if(!BuyWholeStatus.Positions&&!SellWholeStatus.Positions) {
  1044.     if(LossPrices!=0.0) {
  1045.       GlobalVariableDel(LOSSPRICES_NAME);
  1046.       LossPrices = 0.0 ;
  1047.     }
  1048.   }
  1049.  
  1050.   // 金額を更新
  1051.   double CurAmount = BuyWholeStatus.GrossProfit+SellWholeStatus.GrossProfit ;
  1052.   int CurPositions = BuyWholeStatus.Positions+SellWholeStatus.Positions ;
  1053.   UpdateAmount(CurAmount,CurPositions);
  1054.  
  1055.   if(Scalping) {
  1056.     // Sclp タイマー更新
  1057.     bool SclpTiming = false ;
  1058.     if(ScalpingInterval<=0) SclpTiming = true ;
  1059.     else {
  1060.       while(TimeTick-CurSclpInt>=ScalpingInterval) {
  1061.         CurSclpInt+=ScalpingInterval ;
  1062.         SclpTiming = true ;
  1063.       }
  1064.     }
  1065.     // スキャルピング
  1066.     if(SclpTiming&&CurPositions>0) {
  1067.       int flag = 0 ;
  1068.       if(Offsetting) {
  1069.         bool profitSatisfied = ProfitKeepTL>0 &&
  1070.           ( TL(OP_BUY)>=ProfitKeepTL || TL(OP_SELL)>=ProfitKeepTL ) ;
  1071.         if(ScalpingIgnoreTL || !profitSatisfied) {
  1072.           if( (ScalpingProfit!=0.0 && CurAmount>=ScalpingProfit) ||
  1073.               (ScalpingLoss!=0.0 && CurAmount<=ScalpingLoss) ) {
  1074.             flag |= FLAG_BUY|FLAG_SELL ;
  1075.           }
  1076.         }
  1077.       }else {
  1078.         if(BuyWholeStatus.Positions>0) {
  1079.           bool profitSatisfied = ProfitKeepTL>0 && TL(OP_BUY)>=ProfitKeepTL ;
  1080.           if(ScalpingIgnoreTL || !profitSatisfied) {
  1081.             if( (ScalpingProfit!=0.0 && BuyWholeStatus.GrossProfit>=ScalpingProfit) ||
  1082.                 (ScalpingLoss!=0.0 && BuyWholeStatus.GrossProfit<=ScalpingLoss) ) {
  1083.               flag |= FLAG_BUY ;
  1084.             }
  1085.           }
  1086.         }
  1087.         if(SellWholeStatus.Positions>0) {
  1088.           bool profitSatisfied = ProfitKeepTL>0 && TL(OP_SELL)>=ProfitKeepTL ;
  1089.           if(ScalpingIgnoreTL || !profitSatisfied) {
  1090.             if( (ScalpingProfit!=0.0 && SellWholeStatus.GrossProfit>=ScalpingProfit) ||
  1091.                 (ScalpingLoss!=0.0 && SellWholeStatus.GrossProfit<=ScalpingLoss) ) {
  1092.               flag |= FLAG_SELL ;
  1093.             }
  1094.           }
  1095.         }
  1096.       }
  1097.       if(flag!=0) {
  1098.         CheckoutOrderAll(flag);
  1099.         return; // 一旦、戻す
  1100.       }
  1101.     }
  1102.   }
  1103.  
  1104.   // Pmd タイマー更新
  1105.   PmdTiming = false ;
  1106.   if(PyramidingInterval<=0) PmdTiming = true ;
  1107.   else {
  1108.     while(TimeTick-CurPmdInt>=PyramidingInterval) {
  1109.       CurPmdInt+=PyramidingInterval ;
  1110.       PmdTiming = true ;
  1111.     }
  1112.   }
  1113.  
  1114.   // ボーダーライン更新
  1115.   if(!BuyWholeStatus.Positions) {
  1116.     if(BuyBorderLined) {
  1117.       ObjectDelete(BUYBORDER_NAME);
  1118.       BuyBorderLined=false;
  1119.     }
  1120.   }else if(lineUpdTiming||(Offsetting&&SellWholeStatus.Positions>0)) {
  1121.     DrawBorderLine(OP_BUY);
  1122.   }
  1123.   if(!SellWholeStatus.Positions) {
  1124.     if(SellBorderLined) {
  1125.       ObjectDelete(SELLBORDER_NAME);
  1126.       SellBorderLined=false;
  1127.     }
  1128.   }else if(lineUpdTiming||(Offsetting&&BuyWholeStatus.Positions>0)) {
  1129.     DrawBorderLine(OP_SELL);
  1130.   }
  1131.  
  1132.   // 不要なトレールラインを削除
  1133.   if(!BuyWholeStatus.Positions) TrailLine(OP_BUY);
  1134.   if(!SellWholeStatus.Positions) TrailLine(OP_SELL);
  1135.  
  1136.   // オーダーの処理
  1137.   ProcessOrders(nextTimed, OP_BUY, BuyWholeStatus, SellWholeStatus);
  1138.   ProcessOrders(nextTimed, OP_SELL, SellWholeStatus, BuyWholeStatus);
  1139.  
  1140.   // 損益の更新
  1141.   {
  1142.     double newLossPrices = 0.0 ;
  1143.     if(GlobalVariableGet(LOSSPRICES_NAME,newLossPrices)) {
  1144.       LossPrices = newLossPrices ;
  1145.     }
  1146.   }
  1147. }
  1148. //---------------------------------------------------------------------------
  1149. //ボーダーラインを引く
  1150. void DrawBorderLine(int orderType)
  1151. {
  1152.   STATUS status;
  1153.   int pos = CheckStatus(orderType, MAGICMA, status);
  1154.   double borderPrice=status.BorderPrice;
  1155.   if(Offsetting) {
  1156.     // done : borderPrice を medianPrice に置換する
  1157.     STATUS revStatus;
  1158.     CheckStatus(orderType==OP_BUY?OP_SELL:OP_BUY, MAGICMA, revStatus);
  1159.     double medianPrice = status.MedianBorderPrice(revStatus,LossPrices);
  1160.     double offsetPrice = Offsetting?-revStatus.CurrentPrices:0;
  1161.     if(offsetPrice>0) {
  1162.       if(medianPrice!=0.0) borderPrice = medianPrice ;
  1163.       else if(pos>0) {
  1164.         double totalLots = status.TotalLots ;
  1165.         double totalPrice = status.TotalPrices ;
  1166.         if(orderType==OP_BUY) borderPrice = (totalPrice+offsetPrice)/totalLots ;
  1167.         else if(orderType==OP_SELL) borderPrice = (totalPrice-offsetPrice)/totalLots ;
  1168.       }
  1169.     }
  1170.   }
  1171.   double profitPrice = status.ProfitPrice(borderPrice) ;
  1172.   switch(orderType) {
  1173.     case OP_BUY:
  1174.       if(pos) {
  1175.         if(!BuyBorderLined) {
  1176.           ObjectCreate(BUYBORDER_NAME,OBJ_HLINE,0,0,profitPrice);
  1177.           BuyBorderLined = true ;
  1178.         }
  1179.         ObjectSet(BUYBORDER_NAME, OBJPROP_STYLE, STYLE_DOT);
  1180.         ObjectSet(BUYBORDER_NAME, OBJPROP_COLOR, ClrLongBorder);
  1181.         ObjectSet(BUYBORDER_NAME, OBJPROP_PRICE1, profitPrice);
  1182.       }else if(BuyBorderLined) {
  1183.         ObjectDelete(BUYBORDER_NAME);
  1184.         BuyBorderLined = false ;
  1185.       }
  1186.       break;
  1187.     case OP_SELL:
  1188.       if(pos) {
  1189.         if(!SellBorderLined) {
  1190.           ObjectCreate(SELLBORDER_NAME,OBJ_HLINE,0,0, profitPrice);
  1191.           SellBorderLined = true ;
  1192.         }
  1193.         ObjectSet(SELLBORDER_NAME, OBJPROP_STYLE, STYLE_DOT);
  1194.         ObjectSet(SELLBORDER_NAME, OBJPROP_COLOR, ClrShortBorder);
  1195.         ObjectSet(SELLBORDER_NAME, OBJPROP_PRICE1, profitPrice);
  1196.       }else if(SellBorderLined) {
  1197.         ObjectDelete(SELLBORDER_NAME);
  1198.         SellBorderLined = false ;
  1199.       }
  1200.       break;
  1201.   }
  1202. }
  1203. //---------------------------------------------------------------------------
  1204. //ボーダーラインを消去
  1205. void DeleteBorderLines()
  1206. {
  1207.   if(BuyBorderLined) {
  1208.     ObjectDelete(BUYBORDER_NAME);
  1209.     BuyBorderLined = false ;
  1210.   }
  1211.   if(SellBorderLined) {
  1212.     ObjectDelete(SELLBORDER_NAME);
  1213.     SellBorderLined = false ;
  1214.   }
  1215. }
  1216. //---------------------------------------------------------------------------
  1217. //トレールラインを引く
  1218. void TrailLine(int orderType, double price=0.0)
  1219. {
  1220.   switch(orderType) {
  1221.     case OP_BUY:
  1222.       if(price>0.0) {
  1223.         if(!BuyTrailLined) {
  1224.           ObjectCreate(BUYTRAIL_NAME,OBJ_HLINE,0,0, price);
  1225.           BuyTrailLined = true ;
  1226.         }
  1227.         ObjectSet(BUYTRAIL_NAME, OBJPROP_STYLE, STYLE_SOLID);
  1228.         ObjectSet(BUYTRAIL_NAME, OBJPROP_COLOR, ClrTrailBorder);
  1229.         ObjectSet(BUYTRAIL_NAME, OBJPROP_PRICE1, price);
  1230.       }else if(BuyTrailLined) {
  1231.         ObjectDelete(BUYTRAIL_NAME);
  1232.         BuyTrailLined = false ;
  1233.       }
  1234.       break;
  1235.     case OP_SELL:
  1236.       if(price>0.0) {
  1237.         if(!SellTrailLined) {
  1238.           ObjectCreate(SELLTRAIL_NAME,OBJ_HLINE,0,0, price);
  1239.           SellTrailLined = true ;
  1240.         }
  1241.         ObjectSet(SELLTRAIL_NAME, OBJPROP_STYLE, STYLE_SOLID);
  1242.         ObjectSet(SELLTRAIL_NAME, OBJPROP_COLOR, ClrTrailBorder);
  1243.         ObjectSet(SELLTRAIL_NAME, OBJPROP_PRICE1, price);
  1244.       }else if(SellTrailLined) {
  1245.         ObjectDelete(SELLTRAIL_NAME);
  1246.         SellTrailLined = false ;
  1247.       }
  1248.       break;
  1249.   }
  1250. }
  1251. //---------------------------------------------------------------------------
  1252. //トレールの価格を取得
  1253. double TrailPrice(int orderType)
  1254. {
  1255.   switch(orderType) {
  1256.     case OP_BUY:
  1257.       if(BuyTrailLined) {
  1258.         return ObjectGet(BUYTRAIL_NAME, OBJPROP_PRICE1);
  1259.       }
  1260.       break;
  1261.     case OP_SELL:
  1262.       if(SellTrailLined) {
  1263.         return ObjectGet(SELLTRAIL_NAME, OBJPROP_PRICE1);
  1264.       }
  1265.       break;
  1266.   }
  1267.   return 0.0;
  1268. }
  1269. //---------------------------------------------------------------------------
  1270. //MARK:オーダーの処理
  1271. void ProcessOrders(bool nextTimed, int orderType, const STATUS &status, const STATUS &revStatus)
  1272. {
  1273.   if(status.Positions<=0) return ;
  1274.  
  1275.   // done : borderPrice を medianPrice に置換する
  1276.  
  1277.   double totalLots = status.TotalLots ;
  1278.   double totalPrice = status.TotalPrices ;
  1279.   double borderPrice = status.BorderPrice ;
  1280.   double medianPrice = status.MedianBorderPrice(revStatus,LossPrices) ;
  1281.   double offsetPrice = Offsetting?-revStatus.CurrentPrices-LossPrices:0;
  1282.   bool offs = Offsetting && offsetPrice>0 ;
  1283.   if(offs) {
  1284.     if(medianPrice!=0.0) borderPrice = medianPrice;
  1285.     else if(orderType==OP_BUY) borderPrice = (totalPrice+offsetPrice)/totalLots ;
  1286.     else if(orderType==OP_SELL) borderPrice = (totalPrice-offsetPrice)/totalLots ;
  1287.   }
  1288.   double profitPrice = status.ProfitPrice(borderPrice) ;
  1289.   bool underPrice = false ;
  1290.  
  1291.   // Profit Time Limited タイマー更新
  1292.   bool profitSatisfied = orderType==OP_SELL?(profitPrice>Ask):(Bid>profitPrice) ;
  1293.   if(nextTimed) {
  1294.     if(ProfitKeepTL>0) {
  1295.       if(profitSatisfied)
  1296.         TL(orderType,1);
  1297.       else if(TL(orderType)<ProfitKeepTL)
  1298.         TLInit(orderType) ;
  1299.     }
  1300.   }
  1301.   /*
  1302.   if(offsetPrice>0&&profitSatisfied) {
  1303.     if(ProfitKeepTL>0)
  1304.       TL(orderType,ProfitKeepTL-TL(orderType));
  1305.   }
  1306.   */
  1307.   bool timeLimited =
  1308.     (ProfitKeepTL>0 && TL(orderType)>=ProfitKeepTL);
  1309.  
  1310.   int orderFlag=0, revOrderFlag=0, revOrderType=0;
  1311.   switch(orderType) {
  1312.     case OP_BUY:
  1313.       if(status.BorderPrice>Bid) underPrice = true;
  1314.       orderFlag = FLAG_BUY ;
  1315.       revOrderFlag = FLAG_SELL ;
  1316.       revOrderType = OP_SELL ;
  1317.       break;
  1318.     case OP_SELL:
  1319.       if(status.BorderPrice<Ask) underPrice = true;
  1320.       orderFlag = FLAG_SELL ;
  1321.       revOrderFlag = FLAG_BUY ;
  1322.       revOrderType = OP_BUY ;
  1323.       break;
  1324.   }
  1325.  
  1326.   if(underPrice) {
  1327.     bool losscut = false ;
  1328.     /*
  1329.     if(Offsetting&&OffsettingExpireMinutes>0) {
  1330.       if(revStatus.Positions>0) {
  1331.         losscut = TimeCurrent() - MathMax(status.MaxOpenTime,revStatus.MaxOpenTime) >= OffsettingExpireMinutes*60 ;
  1332.       }
  1333.     }
  1334.     */
  1335.     if(!losscut) {
  1336.       double deltaSl = Stoploss * Point ;
  1337.       if(deltaSl>0.0) {
  1338.         switch(orderType) {
  1339.           case OP_BUY:
  1340.             if(!Offsetting) {
  1341.               if(status.MinPrice-Bid>=deltaSl)
  1342.                 losscut = true ;
  1343.             }
  1344.             break;
  1345.           case OP_SELL:
  1346.             if(!Offsetting) {
  1347.               if(Ask-status.MaxPrice>=deltaSl)
  1348.                 losscut = true ;
  1349.             }
  1350.             break;
  1351.         }
  1352.       }
  1353.     }
  1354.     if(losscut) {
  1355.       //損切
  1356.       CheckoutOrderAll(orderFlag);
  1357.       if(Offsetting) {
  1358.         double oldLossPrices=LossPrices, newLossPrices = 0.0 ;
  1359.         if(GlobalVariableGet(LOSSPRICES_NAME,oldLossPrices)) {
  1360.           newLossPrices = oldLossPrices ;
  1361.         }
  1362.         newLossPrices += status.CurrentPrices ;
  1363.         GlobalVariableSet(LOSSPRICES_NAME,newLossPrices);
  1364.       }
  1365.       /*
  1366.       if(offs) {
  1367.         CheckoutOrderAll(revOrderFlag);
  1368.       }*/
  1369.     }else if(PmdTiming) {
  1370.       double stride = PyramidingStride * Point ;
  1371.       bool canAverage = Averaging&&(!AveragingTimes||status.AveragePositions<AveragingTimes);
  1372.       if(canAverage) {
  1373.         if(Offsetting) {
  1374.           // DONE : ナンピンするかダイバージェンスするかはMAを見て決めるようにする
  1375.           double FastMA = ShortTermMA(0) ;
  1376.           double SlowMA = LongTermMA(0) ;
  1377.           canAverage = (orderType==OP_BUY && FastMA>SlowMA) || (orderType==OP_SELL && FastMA<SlowMA);
  1378.           if(canAverage) {
  1379.             if(revStatus.Positions>0) { // ダイバージェンスポジションが既に存在する
  1380.               //ナンピンできる動きをしたかプライスアクションを調べる
  1381.               switch(orderType) {
  1382.                 case OP_BUY: {
  1383.                   double border = status.MinPrice-stride ;
  1384.                   //プライスがボーダーラインを上から下に割り込んだかどうか
  1385.                   canAverage = PmdPrevAsk>=border && Ask<=border ;
  1386.                   break;
  1387.                 }
  1388.                 case OP_SELL: {
  1389.                   double border = status.MaxPrice+stride ;
  1390.                   //プライスがボーダーラインを下から上に突き抜けたかどうか
  1391.                   canAverage = PmdPrevBid<=border && Bid>=border ;
  1392.                   break;
  1393.                 }
  1394.               }
  1395.             }
  1396.           }
  1397.         }
  1398.       }
  1399.       if(canAverage) {
  1400.         //ナンピン
  1401.         double sl=0.0, tp=0.0;
  1402.         canAverage = (orderType==OP_BUY && Ask<=status.MinPrice-stride) ||
  1403.           (orderType==OP_SELL && Bid>=status.MaxPrice+stride);
  1404.         /*switch(orderType) {
  1405.           case OP_BUY:
  1406.             sl = Bid - (Stoploss * Point);
  1407.             if(Takeprofit!=0.0) {
  1408.               tp = Ask + (Takeprofit * Point);
  1409.               if(status.MaxTakeprofit>tp)
  1410.                 tp = status.MaxTakeprofit ;
  1411.             }
  1412.             break;
  1413.           case OP_SELL:
  1414.             sl = Ask + (Stoploss * Point);
  1415.             if(Takeprofit!=0.0) {
  1416.               tp = Bid - (Takeprofit * Point);
  1417.               if(status.MinTakeprofit<tp)
  1418.                 tp = status.MinTakeprofit ;
  1419.             }
  1420.             break;
  1421.         }*/
  1422.         if(canAverage) {
  1423.           double lots = 0.0 ;
  1424.           switch(orderType) {
  1425.             case OP_BUY:
  1426.               if(BuyTLEntried)       lots += Lots ;
  1427.               if(BuyFastMAEntried)   lots += Lots ;
  1428.               if(BuyMediumMAEntried) lots += Lots ;
  1429.               break;
  1430.             case OP_SELL:
  1431.               if(SellTLEntried)       lots += Lots ;
  1432.               if(SellFastMAEntried)   lots += Lots ;
  1433.               if(SellMediumMAEntried) lots += Lots ;
  1434.               break;
  1435.           }
  1436.           if(Offsetting) {
  1437.             lots += revStatus.TotalLots * OffsettingDvgnScale ;
  1438.           }
  1439.           for(int i=0;i<=status.AveragePositions;i++) {
  1440.             lots *= AveragingScale ;
  1441.           }
  1442.           bool done = MakeOrder(orderType,-lots,sl,tp,"AVRG",MAGICMA) ;
  1443.           if(done) {
  1444.             // sl 値をすべて更新する
  1445.             /*if(orderType==OP_BUY?sl<status.MinStoploss:sl>status.MaxStoploss) {
  1446.               for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
  1447.                 if( OrderSelect(i, SELECT_BY_POS) ) {
  1448.                   if( OrderSymbol() != Symbol() ) continue ;
  1449.                   if( magic != OrderMagicNumber() ) continue ;
  1450.                   if( orderType != OrderType() ) continue ;
  1451.                   OrderModify(OrderTicket(), OrderOpenPrice(), sl,
  1452.                     OrderTakeProfit(), OrderExpiration(),
  1453.                      orderType==OP_BUY?clrBlue:clrRed);
  1454.                 }
  1455.               }
  1456.             }*/
  1457.             //ボーダーライン更新
  1458.             DrawBorderLine(orderType);
  1459.           }
  1460.         }
  1461.       }else if(Offsetting&&!revStatus.Positions) {
  1462.         // ダイバージェンス
  1463.         bool canOffset = false ;
  1464.         switch(orderType) {
  1465.           case OP_BUY:
  1466.             if(Bid<=status.MinPrice-stride) {
  1467.               BuyMaxPrice = status.MaxPrice ; // 最高値をリセットしておく
  1468.               canOffset = true ;
  1469.             }
  1470.             break;
  1471.           case OP_SELL:
  1472.             if(Ask>=status.MaxPrice+stride) {
  1473.               SellMinPrice = status.MinPrice ; // 最低値をリセットしておく
  1474.               canOffset = true ;
  1475.             }
  1476.             break;
  1477.         }
  1478.         if(canOffset) {
  1479.           EntryPosition("DVGN", revOrderType, Lots);
  1480.         }
  1481.       }
  1482.     }
  1483.   }else /*if(!underPrice)*/ do {
  1484.     //Entried値を取得
  1485.     bool TLEntried = orderType==OP_BUY?BuyTLEntried:SellTLEntried;
  1486.     bool FastMAEntried = orderType==OP_BUY?BuyFastMAEntried:SellFastMAEntried;
  1487.     bool MediumMAEntried = orderType==OP_BUY?BuyMediumMAEntried:SellMediumMAEntried;
  1488.     double orderDenom=0.0;
  1489.     if(TLEntried) orderDenom+=1.0;
  1490.     if(FastMAEntried) orderDenom+=1.0;
  1491.     if(MediumMAEntried) orderDenom+=1.0;
  1492.     //ピラミッティング
  1493.     if(PmdTiming) {
  1494.       double stride = orderType==OP_BUY ? Ask-status.MaxPrice : status.MinPrice-Bid ;
  1495.       bool canPyramid = stride >= PyramidingStride*Point ;
  1496.       if(canPyramid) {
  1497.         if(!timeLimited) {
  1498.           //利確ロット調整
  1499.           double curTotalLots = totalLots ;
  1500.           if(Offsetting) curTotalLots -= revStatus.TotalLots ;
  1501.           if(curTotalLots>=ProfitTotalLots) canPyramid = false ;
  1502.         }
  1503.       }
  1504.       if(canPyramid) {
  1505.         if(!PyramidingTimes||status.PyramidPositions<PyramidingTimes) {
  1506.           double lots = 0.0 ;
  1507.           switch(orderType) {
  1508.             case OP_BUY:
  1509.               if(BuyTLEntried)       lots += Lots ;
  1510.               if(BuyFastMAEntried)   lots += Lots ;
  1511.               if(BuyMediumMAEntried) lots += Lots ;
  1512.               break;
  1513.             case OP_SELL:
  1514.               if(SellTLEntried)       lots += Lots ;
  1515.               if(SellFastMAEntried)   lots += Lots ;
  1516.               if(SellMediumMAEntried) lots += Lots ;
  1517.               break;
  1518.           }
  1519.           if(Offsetting) {
  1520.             lots += revStatus.TotalLots * OffsettingDvgnScale ;
  1521.           }
  1522.           int si=0;
  1523.           double scale = PyramidingScale;
  1524.           for(int i=si;i<=status.PyramidPositions;i++) {
  1525.             lots *= scale ;
  1526.             if(lots<MinLots) break;
  1527.             if(lots>MaxLots) break;
  1528.           }
  1529.           if(lots<MinLots) lots = MinLots ;
  1530.           if(lots>MaxLots) lots = MaxLots ;
  1531.           double sl = 0.0, tp =0.0 ;
  1532.           double mulLots = lots*orderDenom;
  1533.           if(MakeOrder(orderType,-lots,sl,tp,"PRMD",MAGICMA)) {
  1534.             //tp値更新
  1535.             //UpdateSlTp(orderType,0,tp);
  1536.             //ボーダーライン更新
  1537.             DrawBorderLine(orderType);
  1538.             break;
  1539.           }
  1540.         }
  1541.       }
  1542.     }
  1543.     //Sl値自動更新
  1544.     /*
  1545.     if(MoveStoploss) {
  1546.       UpdateSlTp(orderType);
  1547.     }
  1548.     */
  1549.     if(profitSatisfied) {
  1550.       //利確処理
  1551.       double deltaTp = Takeprofit * Point ;
  1552.       if(deltaTp>0.0) {
  1553.         bool orderMustClose = false ;
  1554.         if(orderType==OP_BUY) {
  1555.           if(Bid-borderPrice/*status.MaxPrice*/>=deltaTp)
  1556.             orderMustClose = true ;
  1557.         }else if(orderType==OP_SELL) {
  1558.           if(/*status.MinPrice*/borderPrice-Ask>=deltaTp)
  1559.             orderMustClose = true ;
  1560.         }
  1561.         if(orderMustClose) {
  1562.           CheckoutOrderAll(orderFlag);
  1563.           if(offs) {
  1564.             CheckoutOrderAll(revOrderFlag);
  1565.           }
  1566.           break;
  1567.         }
  1568.       }
  1569.     }else if(offs&&revStatus.TotalLots<=status.TotalLots) {
  1570.       //損切処理
  1571.       double deltaSl = Stoploss * Point ;
  1572.       if(deltaSl>0.0) {
  1573.         bool orderMustClose = false ;
  1574.         if(orderType==OP_BUY) {
  1575.           if(Bid-status.BorderPrice/*status.MaxPrice*/>=deltaSl)
  1576.             orderMustClose = true ;
  1577.         }else if(orderType==OP_SELL) {
  1578.           if(/*status.MinPrice*/status.BorderPrice-Ask>=deltaSl)
  1579.             orderMustClose = true ;
  1580.         }
  1581.         if(orderMustClose) {
  1582.           CheckoutOrderAll(orderFlag);
  1583.           if(offs) {
  1584.             CheckoutOrderAll(revOrderFlag);
  1585.           }
  1586.           break;
  1587.         }
  1588.       }
  1589.     }
  1590.     if(timeLimited) {
  1591.       // 時間が経過した
  1592.       double Mid = (Ask+Bid)/2.0 ;
  1593.       double FastMA0 = iMA(NULL, MainTimeFrame, FastMAPeriod, MAShift, MAMode, MAPriceType, 0);
  1594.       double MediumMA0 = iMA(NULL, MainTimeFrame, MediumMAPeriod, MAShift, MAMode, MAPriceType, 0);
  1595.       if( (orderType==OP_BUY && Bid>borderPrice) ||
  1596.           (orderType==OP_SELL && Ask<borderPrice) ) { // 利確決済可能
  1597.         double trailLine = borderPrice ;
  1598.         if( (orderType==OP_BUY && Bid>profitPrice) ||
  1599.             (orderType==OP_SELL && Ask<profitPrice) ) { // profit決済可能
  1600.           trailLine = profitPrice ;
  1601.         }
  1602.         double trailPrice = TrailPrice(orderType);
  1603.         if(trailPrice==0.0) {
  1604.           TrailLine(orderType,trailLine);
  1605.         }else {
  1606.           if(orderType==OP_BUY) {
  1607.             if(trailLine>trailPrice)
  1608.               TrailLine(orderType,trailLine);
  1609.           }else if(orderType==OP_SELL) {
  1610.             if(trailLine<trailPrice)
  1611.               TrailLine(orderType,trailLine);
  1612.           }
  1613.         }
  1614.         if(TLEntried) { // Time Limited Position
  1615.           CheckoutOrderAll(orderFlag,orderDenom);
  1616.           TLEntried = false ;
  1617.           if(offs) {
  1618.             CheckoutOrderAll(revOrderFlag,orderDenom);
  1619.           }
  1620.           orderDenom-=1.0;
  1621.         }
  1622.         if(FastMAEntried) {  // Fast MA Position
  1623.           bool orderMustClose = false ;
  1624.           if( (orderType==OP_BUY && Mid<=FastMA0) ||
  1625.               (orderType==OP_SELL && Mid>=FastMA0)  ) { // 利益が Fast MA 以下になっている
  1626.             orderMustClose = true ;
  1627.           }
  1628.           if(orderMustClose) {
  1629.             CheckoutOrderAll(orderFlag,orderDenom);
  1630.             FastMAEntried = false ;
  1631.             if(offs) {
  1632.               CheckoutOrderAll(revOrderFlag,orderDenom);
  1633.             }
  1634.             orderDenom-=1.0;
  1635.           }
  1636.         }
  1637.         if(MediumMAEntried) { // Medium MA Position
  1638.           bool orderMustClose = false ;
  1639.           if( (orderType==OP_BUY && Mid<=MediumMA0) ||
  1640.               (orderType==OP_SELL && Mid>=MediumMA0)  ) { // 利益が Medium MA 以下になっている
  1641.             orderMustClose = true ;
  1642.           }
  1643.           if(orderMustClose) {
  1644.             CheckoutOrderAll(orderFlag);
  1645.             MediumMAEntried = false ;
  1646.             if(offs) {
  1647.               CheckoutOrderAll(revOrderFlag);
  1648.             }
  1649.             orderDenom=0.0;
  1650.           }
  1651.         }
  1652.       }
  1653.       /*
  1654.       if(orderDenom>=1.0)
  1655.         UpdateSlTp(orderType,borderPrice);
  1656.       */
  1657.     }
  1658.     bool expired = !profitSatisfied &&
  1659.       offs && OffsettingExpireMinutes>0 &&
  1660.       TimeCurrent() - MathMin(status.MinOpenTime,revStatus.MinOpenTime) >= OffsettingExpireMinutes*60 ;
  1661.     if(expired) {
  1662.       if(revStatus.TotalLots<status.TotalLots) {
  1663.         // 損切逆トレーリング
  1664.         double trailLine = ( borderPrice + status.BorderPrice ) / 2.0 ;
  1665.         double trailPrice = TrailPrice(revOrderType);
  1666.         if(trailLine!=0.0) {
  1667.           if(trailPrice==0.0) { // 初回トレール
  1668.             TrailLine(revOrderType, trailLine);
  1669.           }else {
  1670.             switch(orderType) { // TP Trailing
  1671.               case OP_BUY:
  1672.                 if(trailLine>trailPrice) {
  1673.                   TrailLine(revOrderType, trailLine);
  1674.                 }
  1675.                 break;
  1676.               case OP_SELL:
  1677.                 if(trailLine<trailPrice) {
  1678.                   TrailLine(revOrderType, trailLine);
  1679.                 }
  1680.                 break;
  1681.             }
  1682.           }
  1683.         }
  1684.       }else {
  1685.         // 逆トレーリング解除
  1686.         if(TrailPrice(revOrderType)!=0.0)
  1687.           TrailLine(revOrderType);
  1688.       }
  1689.     }
  1690.     if(Trailing||expired) {
  1691.       //トレーリング
  1692.       double medianBorder = offs ? medianPrice : borderPrice ;
  1693.       if(expired) medianBorder = ( borderPrice + status.BorderPrice ) / 2.0 ;
  1694.       if(medianBorder!=0.0) {
  1695.         double trailLine = 0.0;
  1696.         double trailStart = TrailingStart*Point ;
  1697.         double trailPadding = TrailingPadding*Point ;
  1698.         double trailPrice = TrailPrice(orderType);
  1699.         switch(orderType) {
  1700.           case OP_BUY:
  1701.             if(trailPrice>0.0) {
  1702.               trailLine = MathMax(Bid-trailPadding, MathMax(trailPrice,medianBorder) );
  1703.             }
  1704.             else if(Bid-medianBorder>=trailStart) {
  1705.               trailLine = MathMax(Bid-trailPadding, medianBorder);
  1706.             }
  1707.             break;
  1708.           case OP_SELL:
  1709.             if(trailPrice>0.0) {
  1710.               trailLine = MathMin(Ask+trailPadding, MathMin(trailPrice,medianBorder) );
  1711.             }
  1712.             else if(medianBorder-Ask>=trailStart) {
  1713.               trailLine = MathMin(Ask+trailPadding, medianBorder);
  1714.             }
  1715.             break;
  1716.         }
  1717.         if(trailLine!=0.0) {
  1718.           if(trailPrice==0.0) { // 初回トレール
  1719.             TrailLine(orderType, trailLine);
  1720.           }else {
  1721.             switch(orderType) {
  1722.               case OP_BUY:
  1723.                 if(trailLine>trailPrice) {
  1724.                   TrailLine(orderType, trailLine);
  1725.                 }
  1726.                 break;
  1727.               case OP_SELL:
  1728.                 if(trailLine<trailPrice) {
  1729.                   TrailLine(orderType, trailLine);
  1730.                 }
  1731.                 break;
  1732.             }
  1733.           }
  1734.         }
  1735.       }
  1736.     }
  1737.     //損切未然防止処理
  1738.     /*else if(losscut) {
  1739.       UpdateSlTp(orderType,borderPrice);
  1740.     }*/
  1741.     //損切未然防止処理(ボーダー越えの手前阻止)
  1742.     /*else if(losscutBorder) {
  1743.       double spread = Ask-Bid ;
  1744.       if( (orderType==OP_BUY && BuyMaxPrice>borderPrice+spread && borderPrice+spread>Bid) ||
  1745.           (orderType==OP_SELL && SellMinPrice<borderPrice-spread && borderPrice-spread<Ask) ) {
  1746.         double oc = Bid - iClose(NULL, MainTimeFrame, 1) ;
  1747.         if( (orderType==OP_BUY && oc<0) || (orderType==OP_SELL && oc>0) )
  1748.           UpdateSlTp(orderType,borderPrice);
  1749.       }
  1750.     }*/
  1751.     //Entried値を戻す
  1752.     switch(orderType) {
  1753.       case OP_BUY:
  1754.         BuyTLEntried = TLEntried ;
  1755.         BuyFastMAEntried = FastMAEntried ;
  1756.         BuyMediumMAEntried = MediumMAEntried ;
  1757.         break;
  1758.       case OP_SELL:
  1759.         SellTLEntried = TLEntried ;
  1760.         SellFastMAEntried = FastMAEntried ;
  1761.         SellMediumMAEntried = MediumMAEntried ;
  1762.         break;
  1763.     }
  1764.   }while(0);
  1765.  
  1766.     //トレールによる利確/損切処理
  1767.     double trailPrice = TrailPrice(orderType);
  1768.     if(trailPrice>0.0) {
  1769.       bool orderMustClose=false;
  1770.       switch(orderType) {
  1771.         case OP_BUY:
  1772.           if(Bid<=trailPrice)
  1773.             orderMustClose=true;
  1774.           break;
  1775.         case OP_SELL:
  1776.           if(Ask>=trailPrice)
  1777.             orderMustClose=true;
  1778.           break;
  1779.       }
  1780.       if(orderMustClose) {
  1781.         CheckoutOrderAll(orderFlag);
  1782.         bool expired = Offsetting && OffsettingExpireMinutes>0 &&
  1783.           TimeCurrent() - MathMin(status.MinOpenTime,revStatus.MinOpenTime) >= OffsettingExpireMinutes*60 ;
  1784.         if(offs||expired) {
  1785.           CheckoutOrderAll(revOrderFlag);
  1786.         }
  1787.       }
  1788.     }
  1789.  
  1790. }
  1791. //---------------------------------------------------------------------------
  1792.  
  1793.   bool InnerPoint(double v, double comp) {
  1794.     return comp-Point/2.0 < v && v < comp+Point/2.0 ;
  1795.   }
  1796.  
  1797. //sl/tpの一括更新
  1798. /*
  1799. void UpdateSlTp(int orderType, double new_sl=0.0, double new_tp=0.0)
  1800. {
  1801.   STATUS status ;
  1802.   //ステータス更新
  1803.   if(!CheckStatus(orderType, MAGICMA, status)) return ;
  1804.   double borderPrice = status.BorderPrice ;
  1805.   double profitPrice = status.ProfitPrice ;
  1806.   double padding = StoplossPadding*Point ;
  1807.   bool overBorder = orderType==OP_BUY ?
  1808.     Bid >= borderPrice+padding : borderPrice-padding >= Ask ;
  1809.   bool overProfit = orderType==OP_BUY ?
  1810.     Bid >= profitPrice+padding : profitPrice-padding >= Ask ;
  1811.   if(overBorder&&!overProfit) {
  1812.     // padding が borderPrice から profitPrice の範囲内にある
  1813.     switch(orderType) {
  1814.       case OP_BUY:
  1815.         profitPrice = Bid-padding ;
  1816.         break;
  1817.       case OP_SELL:
  1818.         profitPrice = Ask+padding ;
  1819.         break;
  1820.     }
  1821.     overProfit = true ;
  1822.   }
  1823.   // sl/tp 値をすべて更新する
  1824.   for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
  1825.     if( OrderSelect(i, SELECT_BY_POS) ) {
  1826.       if( OrderSymbol() != Symbol() ) continue ;
  1827.       if( MAGICMA != OrderMagicNumber() ) continue ;
  1828.       if( orderType != OrderType() ) continue ;
  1829.       double sl = new_sl, tp = new_tp ;
  1830.       double orderStoploss = OrderStopLoss();
  1831.       double orderTakeprofit = OrderTakeProfit();
  1832.       if(new_sl==0.0) {
  1833.         if( overProfit && MoveStoploss )
  1834.           sl = profitPrice;
  1835.         else
  1836.           sl = orderStoploss;
  1837.       }
  1838.       switch(orderType) {
  1839.         case OP_BUY:
  1840.           if(sl<orderStoploss)
  1841.             sl = orderStoploss;
  1842.           break;
  1843.         case OP_SELL:
  1844.           if(sl>orderStoploss)
  1845.             sl = orderStoploss;
  1846.           break;
  1847.       }
  1848.       if(new_tp==0.0)
  1849.         tp = orderTakeprofit;
  1850.       if(InnerPoint(sl,orderStoploss)) sl = orderStoploss ;
  1851.       if(InnerPoint(tp,orderTakeprofit)) tp = orderTakeprofit ;
  1852.       if(sl!=orderStoploss||tp!=orderTakeprofit) {
  1853.         if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl, tp,
  1854.             OrderExpiration(), orderType==OP_BUY?ClrLongArrow:ClrShortArrow)) {
  1855.           PrintLastError();
  1856.         }
  1857.       }
  1858.     }
  1859.   }
  1860. }
  1861. */
  1862. //---------------------------------------------------------------------------
  1863. //TL(TimeLimited)タイマー
  1864. void TLInit(int orderType)
  1865. {
  1866.   switch(orderType) {
  1867.     case OP_BUY: BuyKeepTimer=0; break;
  1868.     case OP_SELL: SellKeepTimer=0; break;
  1869.   }
  1870. }
  1871. //----
  1872. int TL(int orderType, int inc=0)
  1873. {
  1874.   switch(orderType) {
  1875.     case OP_BUY:
  1876.       BuyKeepTimer+=inc ;
  1877.       return BuyKeepTimer;
  1878.     case OP_SELL:
  1879.       SellKeepTimer+=inc ;
  1880.       return SellKeepTimer;
  1881.   }
  1882.   return 0;
  1883. }
  1884. //---------------------------------------------------------------------------
  1885. //すでに注文済みかどうか
  1886. int AlreadyOrdered(int orderFlag, int magic)
  1887. {
  1888.   int flag = 0 ;
  1889.   for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
  1890.     if( OrderSelect(i, SELECT_BY_POS) ) {
  1891.       int orderMagic = OrderMagicNumber() ;
  1892.       if( OrderSymbol() == Symbol() && magic==orderMagic ){
  1893.         if( OrderType() == OP_BUY && (orderFlag&FLAG_BUY)!=0 ){
  1894.           flag |= FLAG_BUY  ; if(flag==orderFlag) break;
  1895.         }else if( OrderType() == OP_SELL && (orderFlag&FLAG_SELL)!=0 ){
  1896.           flag |= FLAG_SELL ; if(flag==orderFlag) break;
  1897.         }
  1898.       }
  1899.     }
  1900.   }
  1901.   return flag;
  1902. }
  1903. //---------------------------------------------------------------------------
  1904. //キーキャンドルスティックのsl値を返す
  1905. /*
  1906. double StoplossKCSSl(int entryType)
  1907. {
  1908.   double sl = entryType==OP_BUY ? Bid : Ask ;
  1909.   for(int i=1;i<=StoplossKCSDuration;i++) {
  1910.     switch(entryType) {
  1911.       case OP_BUY: {
  1912.         double cls = iLow(Symbol(),MainTimeFrame,i);
  1913.         if(cls<sl) sl = cls ;
  1914.         break;
  1915.       }
  1916.       case OP_SELL: {
  1917.         double cls = iHigh(Symbol(),MainTimeFrame,i) + (Ask-Bid) ;  // Spread分、足す
  1918.         if(cls>sl) sl = cls ;
  1919.         break;
  1920.       }
  1921.     }
  1922.   }
  1923.   return sl;
  1924. }
  1925. */
  1926. //---------------------------------------------------------------------------
  1927. //EA用ポジションのエントリー
  1928. bool EAEntryPosition(string detector, int orderFlag, int &busy)
  1929. {
  1930.   // EAの注文を処理
  1931.   if((PositionFlag&orderFlag)!=0&&(busy&orderFlag)==0) {
  1932.     if(!busy||(PositionFlag&FLAG_DUPLEX)!=0) {
  1933.       int entry = orderFlag == FLAG_BUY ? OP_BUY : OP_SELL ;
  1934.       EntryPosition(detector, entry, Lots);
  1935.       busy |= orderFlag ;
  1936.       return true ;
  1937.     }
  1938.   }
  1939.   return false ;
  1940. }
  1941. //---------------------------------------------------------------------------
  1942. //ポジションのエントリー(注文の発注簡易版)
  1943. bool EntryPosition(string detector, int entryType, double lots, int magic=0, double sl=-1.0, double tp=-1.0)
  1944. {
  1945.   switch(entryType) {
  1946.     case OP_BUY:
  1947.       if(sl<0.0) {
  1948.       /*
  1949.         sl = Bid - (Stoploss * Point);
  1950.         if(StoplossKCS) {
  1951.           double kcsSl = StoplossKCSSl(OP_BUY);
  1952.           if(sl<kcsSl) sl = kcsSl ;
  1953.         }
  1954.       */ sl=0.0;
  1955.       }
  1956.       if(tp<0.0) {
  1957.         tp=0.0;
  1958.         /*if(Takeprofit!=0.0)
  1959.           tp = Ask + (Takeprofit * Point);*/
  1960.       }
  1961.       BuyTLEntried=EntryTLPos;
  1962.       BuyFastMAEntried=EntryFastMAPos;
  1963.       BuyMediumMAEntried=EntryMediumMAPos;
  1964.       break;
  1965.     case OP_SELL:
  1966.       if(sl<0.0) {
  1967.       /*
  1968.         sl = Ask + (Stoploss * Point);
  1969.         if(StoplossKCS) {
  1970.           double kcsSl = StoplossKCSSl(OP_SELL);
  1971.           if(sl>kcsSl) sl = kcsSl ;
  1972.         }
  1973.       */ sl=0.0;
  1974.       }
  1975.       if(tp<0.0) {
  1976.         tp = 0.0 ;
  1977.         /*if(Takeprofit!=0.0)
  1978.           tp = Bid - (Takeprofit * Point);*/
  1979.       }
  1980.       SellTLEntried=EntryTLPos;
  1981.       SellFastMAEntried=EntryFastMAPos;
  1982.       SellMediumMAEntried=EntryMediumMAPos;
  1983.       break;
  1984.   }
  1985.   bool res = MakeOrder(entryType,lots,sl,tp,detector,magic) ;
  1986.   if(res) {
  1987.     switch(entryType) {
  1988.       case OP_BUY:
  1989.         BuyMaxPrice = Ask ;
  1990.         BuyLosscutTimer = 0 ;
  1991.         break;
  1992.       case OP_SELL:
  1993.         SellMinPrice = Bid ;
  1994.         SellLosscutTimer = 0 ;
  1995.         break;
  1996.     }
  1997.     TLInit(entryType);
  1998.   }
  1999.   return res ;
  2000. }
  2001. //---------------------------------------------------------------------------
  2002. //注文の発注
  2003. bool MakeOrder(int entryType, double lots, double sl, double tp, string detector, int magic)
  2004. {
  2005.   bool entried=false ;
  2006.  
  2007.   double mulLots = 0.0 ;
  2008.  
  2009.   if(lots<0) {
  2010.     lots=-lots;
  2011.     mulLots=1.0;
  2012.   }else {
  2013.     switch(entryType) {
  2014.       case OP_BUY:
  2015.         if(BuyTLEntried)       mulLots += 1.0 ;
  2016.         if(BuyFastMAEntried)   mulLots += 1.0 ;
  2017.         if(BuyMediumMAEntried) mulLots += 1.0 ;
  2018.         break;
  2019.       case OP_SELL:
  2020.         if(SellTLEntried)       mulLots += 1.0 ;
  2021.         if(SellFastMAEntried)   mulLots += 1.0 ;
  2022.         if(SellMediumMAEntried) mulLots += 1.0 ;
  2023.         break;
  2024.     }
  2025.   }
  2026.  
  2027.  
  2028.   if(mulLots==0.0) return false ;
  2029.  
  2030.   for(int retry=0; retry<ORDER_RETRY; retry++) {
  2031.  
  2032.     if(MarketInfo(NULL,MODE_SPREAD) > Spread) { Sleep(2000); continue ; }
  2033.  
  2034.     double entryPrice = 0.0 ;
  2035.     color orderColor = clrNONE;
  2036.  
  2037.     switch(entryType) {
  2038.     case OP_BUY:
  2039.       entryPrice = Ask ;
  2040.       orderColor = ClrLongArrow ;
  2041.       break;
  2042.     case OP_SELL:
  2043.       entryPrice = Bid ;
  2044.       orderColor = ClrShortArrow ;
  2045.       break;
  2046.     }
  2047.  
  2048.     if(!entried) {
  2049.       if(MakeOrderSub(entryType,entryPrice,lots*mulLots,sl,tp,ENTRY_NAME"("+detector+")",magic,orderColor))
  2050.         entried = true ;
  2051.     }
  2052.  
  2053.     if(entried) {
  2054.       return true ;
  2055.     }
  2056.  
  2057.     Sleep(2000);
  2058.   }
  2059.  
  2060.   return false;
  2061. }
  2062. //---------------------------------------------------------------------------
  2063. //注文発注サブルーチン
  2064. bool MakeOrderSub(int entryType, double entryPrice, double lots, double sl, double tp,
  2065.   string comment,int magicNumber,color orderColor)
  2066. {
  2067.    int res = OrderSend(
  2068.                       NULL,
  2069.                       entryType,
  2070.                       lots,
  2071.                       entryPrice,
  2072.                       Slippage,
  2073.                       sl,
  2074.                       tp,
  2075.                       comment,
  2076.                       magicNumber,
  2077.                       0,
  2078.                       orderColor
  2079.                    );
  2080.    if(res<0)
  2081.      PrintLastError();
  2082.    return res>=0;
  2083. }
  2084. //---------------------------------------------------------------------------
  2085. //注文の決済
  2086. bool CheckoutOrder( int orderType, int orderTicket, double orderLots)
  2087. {
  2088.   for(int retry=0; retry<ORDER_RETRY; retry++) {
  2089.     double checkoutPrice = 0.0 ;
  2090.     color orderColor = clrNONE ;
  2091.     switch(orderType) {
  2092.     case OP_BUY:
  2093.       checkoutPrice = Bid ;
  2094.       orderColor = ClrLongArrow ;
  2095.       break;
  2096.     case OP_SELL:
  2097.       checkoutPrice = Ask ;
  2098.       orderColor = ClrShortArrow ;
  2099.       break;
  2100.     }
  2101.     if(orderLots<MinLots) orderLots = MinLots ;
  2102.     if(OrderClose(orderTicket, orderLots, checkoutPrice, Slippage, orderColor))
  2103.       return true;
  2104.     Sleep(100);
  2105.   }
  2106.   PrintLastError();
  2107.   return false ;
  2108. }
  2109. //---------------------------------------------------------------------------
  2110.  
  2111.   struct OBJECT_CHECKOUT {
  2112.     int Ticket;
  2113.     double Profit;
  2114.     OBJECT_CHECKOUT() {
  2115.       Ticket = -1 ;
  2116.       Profit = 0.0 ;
  2117.     }
  2118.     OBJECT_CHECKOUT(int Ticket_, double Profit_) {
  2119.       Ticket = Ticket_ ;
  2120.       Profit = Profit_ ;
  2121.     }
  2122.     bool operator <(const OBJECT_CHECKOUT &rhs) const {
  2123.       return Profit < rhs.Profit ;
  2124.     }
  2125.   };
  2126.  
  2127. //注文の全決済
  2128. bool CheckoutOrderAll(int orderFlag, double lotsDenom=1.0)
  2129. {
  2130.   bool result = true ;
  2131.   CArrayObj *array = new CArrayObj();
  2132.   for(int i = 0 ; i < OrdersTotal() ; i++){
  2133.     if(OrderSelect(i, SELECT_BY_POS)) {
  2134.       int magic = OrderMagicNumber();
  2135.       int orderType = OrderType() ;
  2136.       if( (orderType==OP_BUY&&(orderFlag&FLAG_BUY)!=0) ||
  2137.           (orderType==OP_SELL&&(orderFlag&FLAG_SELL)!=0) ) {
  2138.         if( OrderSymbol() == Symbol() && magic == MAGICMA ){
  2139.           AddToArray(array,OBJECT_CHECKOUT(OrderTicket(),OrderProfit()));
  2140.         }
  2141.       }
  2142.     }
  2143.   }
  2144.   array.Sort(ARRAY_SORT_DESCEND); // 利益が多い順に並べ替える
  2145.   for(int i=0;i<array.Total();i++) {
  2146.     CSortable<OBJECT_CHECKOUT> *node = (CSortable<OBJECT_CHECKOUT>*)array.At(i);
  2147.     if(OrderSelect(node.key.Ticket, SELECT_BY_TICKET)) {
  2148.       if(!CheckoutOrder(OrderType(),OrderTicket(),OrderLots()/lotsDenom)) {
  2149.         result = false ; break;
  2150.       }
  2151.     }
  2152.   }
  2153.   delete array ;
  2154.   return result ;
  2155. }
  2156. //---------------------------------------------------------------------------
  2157. //000,000,000表示
  2158. // http://chocottokozukai.seesaa.net/article/417824756.html
  2159. string DoubleToAmount(double inputdata, int dig)
  2160. {
  2161.   string returnstr = DoubleToStr(inputdata,dig);
  2162.   int length;
  2163.   int noofcomma;
  2164.   int firstcomma;
  2165.  
  2166.   length = StringLen(DoubleToStr(MathFloor(inputdata),0));
  2167.   if (inputdata >= 0) noofcomma = (int)MathFloor((length - 1) / 3);
  2168.   else noofcomma = (int)MathFloor((length - 2) / 3);
  2169.   if (noofcomma == 0) return (returnstr);
  2170.  
  2171.   firstcomma = length - noofcomma * 3;
  2172.   if (firstcomma == 0) firstcomma = 3;
  2173.  
  2174.   for (int i = 0; i < noofcomma; i++){
  2175.     returnstr = StringConcatenate(StringSubstr(returnstr, 0, firstcomma + i * 4),
  2176.       ",",StringSubstr(returnstr, firstcomma + i * 4));
  2177.   }
  2178.  
  2179.   return (returnstr);
  2180. }
  2181. //---------------------------------------------------------------------------
  2182. //短期MA値を返す
  2183. double ShortTermMA(int si)
  2184. {
  2185.   return iMA(NULL, MainTimeFrame, ReferSlowMA?MediumMAPeriod:FastMAPeriod,
  2186.     MAShift, MAMode, MAPriceType, si);
  2187. }
  2188. //-----
  2189. //長期MA値を返す
  2190. double LongTermMA(int si)
  2191. {
  2192.   return iMA(NULL, MainTimeFrame, ReferSlowMA?SlowMAPeriod:MediumMAPeriod,
  2193.     MAShift, MAMode, MAPriceType, si);
  2194. }
  2195. //---------------------------------------------------------------------------
  2196. // MARK: Detector MARSIX
  2197. //-----
  2198. input group  "Detector MAXRSIX ( MA RSI Cross )"
  2199. input bool   MARSIXDetector      = true;  // MARSIX Detector Enabled ( MA RSI Cross )
  2200. input int    MARSIXRangeDuration = 15;    // MARSIX Range Search Duration period
  2201. input int    MARSIXVaildDuration = 5;     // MARSIX Valid Duration period
  2202. input double MARSIXMAMaxDistance = 50.0;  // MARSIX MA Max Distance in points
  2203. input bool   MARSIXMACheckLineUp = false; // MARSIX MA Check Line Up
  2204. input int    MARSIXRSIPeriod     = 14 ;   // MARSIX RSI period
  2205. input ENUM_APPLIED_PRICE MARSIXRSIPriceType = PRICE_CLOSE; // MARSIX RSI Price type
  2206. input double MARSIXRSIBuyXStart  = 55.0;  // MARSIX RSI Buy Cross Start border
  2207. input double MARSIXRSIBuyXEnd    = 69.1;  // MARSIX RSI Buy Cross End border
  2208. input double MARSIXRSISellXStart = 45.0;  // MARSIX RSI Sell Cross Start border
  2209. input double MARSIXRSISellXEnd   = 30.9;  // MARSIX RSI Sell Cross End border
  2210. //-----
  2211. // MA RSI Cross のエントリ状態確認
  2212. int CheckDetectorMARSIX(int si=0)
  2213. {
  2214.   int flag=0, multiFlag=0 ;
  2215.  
  2216.   double maxDist = MARSIXMAMaxDistance*Point ;
  2217.  
  2218.   // 現在の状態を確認
  2219.   double HalfSpread = (Ask-Bid) / 2.0 ;
  2220.   double FastMA0 = ShortTermMA(si)+HalfSpread;
  2221.   double FastMA1 = ShortTermMA(si+1)+HalfSpread;
  2222.   double MediumMA = LongTermMA(si)+HalfSpread;
  2223.   double Distance = DBL_MAX ;
  2224.   double c = iClose(NULL, MainTimeFrame, 1);
  2225.   double RSI0 = iRSI(Symbol(), MainTimeFrame, MARSIXRSIPeriod, MARSIXRSIPriceType, si+0);
  2226.   if(Bid<=FastMA0&&FastMA0<=Ask) { // 検証不能
  2227.     return 0 ;
  2228.   }else if(Bid-c>0&&Ask>FastMA0&&FastMA0-FastMA1>0) {
  2229.     if(Ask-FastMA0<=maxDist && ((!MARSIXMACheckLineUp)||(FastMA0>MediumMA)) ) {
  2230.       if(RSI0>=MARSIXRSIBuyXEnd)
  2231.         flag = FLAG_BUY ;
  2232.     }
  2233.   }else if(Bid-c<0&&Bid<FastMA0&&FastMA0-FastMA1<0) {
  2234.     if(FastMA0-Bid<=maxDist && ((!MARSIXMACheckLineUp)||(FastMA0<MediumMA)) ) {
  2235.       if(RSI0<=MARSIXRSISellXEnd)
  2236.         flag = FLAG_SELL ;
  2237.     }
  2238.   }
  2239.  
  2240.   if(flag) {
  2241.  
  2242.     // RSIのクロスをチェック
  2243.     for (int i=1; i<=MARSIXRangeDuration; i++) {
  2244.  
  2245.       if(!multiFlag&&i>=MARSIXVaildDuration) break; // RSI Cross 検出範囲外
  2246.  
  2247.       double RSI1 = iRSI(Symbol(), MainTimeFrame, MARSIXRSIPeriod, MARSIXRSIPriceType, si+i);
  2248.  
  2249.       if(RSI0>=MARSIXRSIBuyXEnd) { // 買い
  2250.         if(RSI1<=MARSIXRSIBuyXStart) {
  2251.           multiFlag |= FLAG_BUY ;
  2252.           if(multiFlag==(FLAG_BUY|FLAG_SELL)) break;
  2253.           RSI0=RSI1 ;
  2254.           continue;
  2255.         }
  2256.       }else if(RSI0<=MARSIXRSISellXEnd) { // 売り
  2257.         if(RSI1>=MARSIXRSISellXStart) {
  2258.           multiFlag |= FLAG_SELL ;
  2259.           if(multiFlag==(FLAG_BUY|FLAG_SELL)) break;
  2260.           RSI0=RSI1 ;
  2261.           continue;
  2262.         }
  2263.       }else {
  2264.         RSI0=RSI1 ;
  2265.       }
  2266.  
  2267.     }
  2268.  
  2269.     if(flag==multiFlag) {
  2270.       return flag ; // 順張りの売買タイミング
  2271.     }
  2272.  
  2273.   }
  2274.  
  2275.   return 0;
  2276. }
  2277. //---------------------------------------------------------------------------
  2278. // MARK: Detector 2MMX
  2279. // ( https://youtu.be/deBLPlt8N4E )
  2280. //-----
  2281. input group "Detector 2MMX ( 2 Momentum Cross )"
  2282. input bool MMX2Detector        = true ; // 2MMX Detector Enabled ( 2 Momentum Cross )
  2283. input int  MMX2FastPeriod      = 10;    // 2MMX Fast period
  2284. input int  MMX2SlowPeriod      = 34;    // 2MMX Slow period
  2285. input int  MMX2Duration        = 5;     // 2MMX Duration
  2286. input ENUM_APPLIED_PRICE  MMX2PriceType = PRICE_CLOSE; // 2MM Price type
  2287. //-----
  2288. int CheckDetectorMMX2(int si=0)
  2289. {
  2290.   double FastMA0 = ShortTermMA(si);
  2291.   double MediumMA0 = LongTermMA(si);
  2292.   double SlowMM0 = iMomentum(NULL, MainTimeFrame, MMX2SlowPeriod, MMX2PriceType, si);
  2293.   int ma = 0, mm = 0 ;
  2294.  
  2295.   if(FastMA0>MediumMA0) ma = FLAG_BUY ;
  2296.   else if(FastMA0<MediumMA0) ma = FLAG_SELL ;
  2297.  
  2298.   if(SlowMM0>100.0) mm = FLAG_BUY ;
  2299.   else if(SlowMM0<100.0) mm = FLAG_SELL ;
  2300.  
  2301.   if(ma!=0&&ma==mm) {
  2302.  
  2303.     double FastMM0 = iMomentum(NULL, MainTimeFrame, MMX2FastPeriod, MMX2PriceType, si);
  2304.     double FastMM1 = iMomentum(NULL, MainTimeFrame, MMX2FastPeriod, MMX2PriceType, si+1);
  2305.  
  2306.     // Check fast momentum crossing
  2307.     if( mm == FLAG_BUY ? FastMM0>=100.0 && FastMM1<100.0 : FastMM0<=100.0 && FastMM1>100.0) {
  2308.  
  2309.       // Check duration
  2310.       for(int i=1;i<=MMX2Duration;i++) {
  2311.         double FastMAi = ShortTermMA(si+i);
  2312.         double MediumMAi = LongTermMA(si+i);
  2313.         if( mm == FLAG_BUY ? FastMAi < MediumMAi : FastMAi > MediumMAi) return 0;
  2314.         double SlowMMi = iMomentum(NULL, MainTimeFrame, MMX2SlowPeriod, MMX2PriceType, si+i);
  2315.         if( mm == FLAG_BUY ? SlowMMi < 100.0 : SlowMMi > 100.0 ) return 0;
  2316.       }
  2317.  
  2318.       // Valid entry position detected
  2319.       return mm ;
  2320.     }
  2321.  
  2322.   }
  2323.  
  2324.   return 0;
  2325. }
  2326. //---------------------------------------------------------------------------
  2327. // MARK: Detector COBRA
  2328. // ( https://youtu.be/EbGK1FF2Q_c )
  2329. //-----
  2330. input group "Detector COBRA ( RSI-COBRA )"
  2331. input bool COBRADetector      = true ; // COBRA Detector Enabled ( RSI-COBRA )
  2332. input ENUM_APPLIED_PRICE COBRARSIPriceType = PRICE_CLOSE ; // COBRA RSI Price type
  2333. input int  COBRARSIPeriod     = 14 ;   // COBRA RSI period
  2334. input int  COBRAMAPeriod      = 50 ;   // COBRA MA period
  2335. input ENUM_MA_METHOD COBRAMAMethod = MODE_SMA ; // COBRA MA mode
  2336. input int  COBRADuration      = 5;     // COBRA Duration
  2337. //-----
  2338. int CheckDetectorCOBRA(int si=0)
  2339. {
  2340.   double FastMA0 = ShortTermMA(si);
  2341.   double MediumMA0 = LongTermMA(si);
  2342.   int ma=0;
  2343.  
  2344.   if(FastMA0>MediumMA0) ma = FLAG_BUY ;
  2345.   else if(FastMA0<MediumMA0) ma = FLAG_SELL ;
  2346.  
  2347.   if(ma!=0) {
  2348.  
  2349.     // Check duration of Fast and Medium MA line up
  2350.     for(int i=1;i<=COBRADuration;i++) {
  2351.       double FastMAi = ShortTermMA(si+i);
  2352.       double MediumMAi =  LongTermMA(si+i);
  2353.       if( ma == FLAG_BUY ? FastMAi < MediumMAi : FastMAi > MediumMAi) return 0;
  2354.     }
  2355.  
  2356.     // Make array of RSI
  2357.     double arRSI[] ;
  2358.     int nArRSI = COBRAMAPeriod+COBRADuration+1 ;
  2359.     ArrayResize(arRSI,nArRSI);
  2360.     for(int i=0;i<nArRSI;i++) {
  2361.       arRSI[i]=iRSI(NULL, MainTimeFrame, COBRARSIPeriod, COBRARSIPriceType, si+i);
  2362.     }
  2363.  
  2364.     // Check RSI-COBRA entry position
  2365.     double RSIMA0 = iMAOnArray(arRSI, nArRSI, COBRAMAPeriod, MAShift, COBRAMAMethod, 0);
  2366.     if( ma == FLAG_BUY ? RSIMA0>50.0 && arRSI[0]>=RSIMA0 && arRSI[1]<RSIMA0 :
  2367.             RSIMA0<50.0 && arRSI[0]<=RSIMA0 && arRSI[1]>RSIMA0) {
  2368.  
  2369.       // Check duration of RSI->MA line up
  2370.       for(int i=1;i<=COBRADuration;i++) {
  2371.         double RSIMAi = iMAOnArray(arRSI, nArRSI, COBRAMAPeriod, MAShift, COBRAMAMethod, i);
  2372.         if(ma == FLAG_BUY ? RSIMAi<50.0 : RSIMAi>50.0 ) return 0;
  2373.       }
  2374.  
  2375.       // Valid entry position detected
  2376.       return ma ;
  2377.     }
  2378.  
  2379.   }
  2380.  
  2381.   return 0;
  2382. }
  2383. //---------------------------------------------------------------------------
  2384. // MARK: Detector GXRSI
  2385. //-----
  2386. input group "Detector GXRSI ( RSI + MA Golden Cross )"
  2387. input bool   GXRSIDetector      = true ; // GXRSI Detector Enabled ( RSI + MA Golden Cross )
  2388. input int    GXRSIValidDuration = 2;     // GXRSI Valid Duration period
  2389. input int    GXRSIRSIPeriod     = 14 ;   // GXRSI RSI period
  2390. input ENUM_APPLIED_PRICE GXRSIRSIPriceType = PRICE_CLOSE; // GXRSI RSI Price type
  2391. input double GXRSIRSIBuyLine    = 69.1;  // GXRSI RSI Buy Line border
  2392. input double GXRSIRSISellLine   = 30.9;  // GXRSI RSI Sell Line border
  2393. //-----
  2394. int CheckDetectorGXRSI(int si=0)
  2395. {
  2396.   double RSI0 = iRSI(NULL, MainTimeFrame, GXRSIRSIPeriod, GXRSIRSIPriceType, si+0);
  2397.   int rsi = 0, gx = 0 ;
  2398.  
  2399.   if(RSI0>=GXRSIRSIBuyLine) rsi |= FLAG_BUY ;
  2400.   if(RSI0<=GXRSIRSISellLine) rsi |= FLAG_SELL ;
  2401.  
  2402.   if(rsi) { // RSI 買い または 売り の気配あり
  2403.  
  2404.     // MA ゴールデンクロス検出処理
  2405.     double FastMA0 = ShortTermMA(si);
  2406.     double MediumMA0 = LongTermMA(si);
  2407.     for(int i=0;i<GXRSIValidDuration;i++) {
  2408.       double FastMA1 = ShortTermMA(si+i+1);
  2409.       double MediumMA1 = LongTermMA(si+i+1);
  2410.       if(FastMA1<MediumMA1&&FastMA0>=MediumMA0) gx |= FLAG_BUY ;
  2411.       if(FastMA1>MediumMA1&&FastMA0<=MediumMA0) gx |= FLAG_SELL ;
  2412.       FastMA0 = FastMA1 ;
  2413.       MediumMA0 = MediumMA1 ;
  2414.     }
  2415.  
  2416.   }
  2417.  
  2418.   // RSI と MA ゴールデンクロス の 論理積 (両ビット立っているものを返す)
  2419.   return rsi & gx ;
  2420. }
  2421. //---------------------------------------------------------------------------
  2422.  
Tags: Mt4
Advertisement
Add Comment
Please, Sign In to add comment