HYROLEAN

hyrGlobal.mq5

Mar 17th, 2026 (edited)
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.68 KB | Money | 0 0
  1. // hyrGlobal.mq5
  2. //   by 2026 (c)hyrolean
  3. //---------------------------------------------------------------------------
  4. // Local:: <DataFolder>\MQL5\Libraries\User\hyrGlobal.mq5
  5. // URL:: https://pastebin.com/Lw82F2MN
  6. //---------------------------------------------------------------------------
  7. #property copyright "2026, hyrolean"
  8. #property link      "https://pastebin.com/Lw82F2MN"
  9. #property library
  10. //---------------------------------------------------------------------------
  11. #include <Trade/PositionInfo.mqh>
  12. #include <Trade/Trade.mqh>
  13. #include <User/errordescription.mqh> // https://www.mql5.com/ja/code/79
  14. #include <User/hyrDefs.mqh>   // https://pastebin.com/iHZKAWqC
  15. #include <User/hyrTmpl.mqh>   // https://pastebin.com/LG1vurny
  16. #include <User/hyrStatus.mqh> // https://pastebin.com/d9Z8P2qD
  17.  
  18. static string ENTRY_NAME = "hyrEA"; // エントリー名
  19.  
  20. static int MaxAllowedSlippage=10;  // 最大許容スリッページ(points)
  21. static int MaxAllowedSpread=50;    // 最大許容スプレッド(points)
  22.  
  23. static int  ORDER_RETRY = 10 ;            // 注文の最大許容リトライ回数
  24. static int  ORDER_RETRY_SLEEP = 100 ;     // 注文のリトライ時待機時間
  25. static uint ORDER_RETRY_DURATION = 1000 ; // 注文のリトライ最大許容有効時間
  26.  
  27. static CPositionInfo PosInfo ;
  28. static CTrade Trade ;
  29.  
  30. //---------------------------------------------------------------------------
  31. //グローバル変数の設定
  32. void GlobalSettings(
  33.   string entryName,
  34.   int maxSlippage,
  35.   int maxSpread,
  36.   int orderRetry,
  37.   int orderRetrySleep,
  38.   uint orderRetryDuration ) export
  39. {
  40.   ENTRY_NAME = entryName ;
  41.   MaxAllowedSlippage = maxSlippage ;
  42.   MaxAllowedSpread = maxSpread ;
  43.   ORDER_RETRY = orderRetry ;
  44.   ORDER_RETRY_SLEEP = orderRetrySleep ;
  45.   ORDER_RETRY_DURATION = orderRetryDuration ;
  46. }
  47. //---------------------------------------------------------------------------
  48. //エラーログ出力
  49. void PrintLastError(string sender) export
  50. {
  51.   int lastError = GetLastError() ;
  52.   if(sender!="") {
  53.     PrintFormat(ENTRY_NAME+"(%s): error(%d): %s",
  54.       sender,lastError,ErrorDescription(lastError));
  55.   }else {
  56.     PrintFormat(ENTRY_NAME+"error(%d): %s",
  57.       lastError,ErrorDescription(lastError));
  58.   }
  59. }
  60. //---------------------------------------------------------------------------
  61. //メッセージ出力
  62. void PrintMessage(string message, string sender) export
  63. {
  64.   if(sender!="")
  65.     PrintFormat(ENTRY_NAME+"(%s): %s",sender,message);
  66.   else
  67.     PrintFormat(ENTRY_NAME+": %s",message);
  68. }
  69. //---------------------------------------------------------------------------
  70. //vとcompの距離が1Pointのサイズに収まっているかどうか
  71. bool InnerPoint(double v, double comp) export
  72. {
  73.   return comp-_Point/2.0 < v && v < comp+_Point/2.0 ;
  74. }
  75. //---------------------------------------------------------------------------
  76. //基軸時間を返す
  77. datetime BaseTime(ENUM_TIMEBASE TimeBase) export
  78. {
  79.   switch(TimeBase) {
  80.     case TIMEBASE_GMT:               // Greenwich Mean Time (GMT)
  81.       return TimeGMT();
  82.     case TIMEBASE_LOCAL:             // Local Time
  83.       return TimeLocal();
  84.     case TIMEBASE_SERVER:            // Server Time
  85.       return TimeCurrent();
  86.   }
  87.   return 0;
  88. }
  89. //---------------------------------------------------------------------------
  90. //マーケットで扱えるようにロットサイズを補正して返す
  91. double AdjustMarketLots(double lots) export
  92. {
  93.   double minLots = SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
  94.   double stepLots = SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
  95.   double maxLots = SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
  96.   double roundLots = MathRound( MathMax(lots,stepLots) / stepLots ) ;
  97.   return MathMin(MathMax(roundLots*stepLots,minLots),maxLots) ;
  98. }
  99. //---------------------------------------------------------------------------
  100. //すでに注文済みかどうか
  101. FLAG AlreadyOrdered(FLAG orderFlag, MAGIC magic) export
  102. {
  103.   FLAG flag = 0 ;
  104.   for(int i=PositionsTotal()-1 ; i>=0 ; i--) {
  105.     if(PosInfo.SelectByIndex(i)) {
  106.       MAGIC orderMagic = PosInfo.Magic() ;
  107.       if( PosInfo.Symbol() == Symbol() && (magic<0||magic==orderMagic) ){
  108.         OP orderType = PosInfo.PositionType() ;
  109.         if( orderType == OP_BUY && (orderFlag&FLAG_BUY)!=0 ){
  110.           flag |= FLAG_BUY  ; if(flag==orderFlag) break;
  111.         }else if( orderType == OP_SELL && (orderFlag&FLAG_SELL)!=0 ){
  112.           flag |= FLAG_SELL ; if(flag==orderFlag) break;
  113.         }
  114.       }
  115.     }
  116.   }
  117.   return flag;
  118. }
  119. //---------------------------------------------------------------------------
  120. //注文の発注
  121. TICKET MakeOrder(OP entryType, double lots, double sl, double tp, string detector,
  122.   MAGIC magic, double entryPrice, datetime expiration) export
  123. {
  124.   string entryName = ENTRY_NAME+"("+detector+")" ;
  125.  
  126.   uint startTick = GetTickCount();
  127.   for(int retry=0; retry<ORDER_RETRY; retry++) {
  128.  
  129.     if( MaxAllowedSpread<0 || (entryType!=OP_BUY&&entryType!=OP_SELL) ||
  130.         SymbolInfoInteger(NULL,SYMBOL_SPREAD) <= MaxAllowedSpread ) {
  131.       TICKET ticket=MakeOrderSub(
  132.         entryType,entryPrice,lots,sl,tp,entryName,magic,expiration,CLR_NONE);
  133.       if(ticket>0)
  134.         return ticket ;
  135.     }
  136.  
  137.     if(GetTickCount()-startTick>=ORDER_RETRY_DURATION)
  138.       break; // タイムオーバー
  139.  
  140.     Sleep(ORDER_RETRY_SLEEP);
  141.   }
  142.  
  143.   PrintMessage("entry failed.","MakeOrder");
  144.   return 0;
  145. }
  146. //---------------------------------------------------------------------------
  147. //注文発注サブルーチン
  148. TICKET MakeOrderSub(OP entryType, double entryPrice, double lots, double sl, double tp,
  149.   string comment, MAGIC magicNumber, datetime expiration, color orderColor) export
  150. {
  151.   // ※ MT5 では、orderColor は使われない
  152.   Trade.SetDeviationInPoints(MaxAllowedSlippage);
  153.   Trade.SetExpertMagicNumber(magicNumber);
  154.  
  155.   bool res=false ;
  156.   ENUM_ORDER_TYPE_TIME orderTime
  157.    = expiration==0? ORDER_TIME_GTC: ORDER_TIME_SPECIFIED;
  158.   switch(entryType) {
  159.     case OP_BUY:
  160.       res = Trade.Buy(lots, NULL, entryPrice, sl, tp, comment);
  161.       break;
  162.     case OP_SELL:
  163.       res = Trade.Sell(lots, NULL, entryPrice, sl, tp, comment);
  164.       break;
  165.     case OP_BUYLIMIT:
  166.       res = Trade.BuyLimit(lots, entryPrice, NULL, sl, tp, orderTime, expiration, comment);
  167.       break;
  168.     case OP_SELLLIMIT:
  169.       res = Trade.SellLimit(lots, entryPrice, NULL, sl, tp, orderTime, expiration, comment);
  170.       break;
  171.     case OP_BUYSTOP:
  172.       res = Trade.BuyStop(lots, entryPrice, NULL, sl, tp, orderTime, expiration, comment);
  173.       break;
  174.     case OP_SELLSTOP:
  175.       res = Trade.SellStop(lots, entryPrice, NULL, sl, tp, orderTime, expiration, comment);
  176.       break;
  177.     default:
  178.       PrintMessage("Unknown entry type","MakeOrderSub");
  179.       return 0;
  180.   }
  181.  
  182.   if(!res) {
  183.     PrintLastError("MakeOrderSub");
  184.     return 0;
  185.   }
  186.   return Trade.ResultOrder();
  187. }
  188. //---------------------------------------------------------------------------
  189. //リミット価格付き逆指値注文の発注
  190. TICKET MakeOrderStopLimit(double stopPrice, double limitPrice, double lots,
  191.   double sl, double tp, string detector, MAGIC magic, datetime expiration)
  192.   export
  193. {
  194.   string entryName = ENTRY_NAME+"("+detector+")" ;
  195.   ENUM_ORDER_TYPE orderType = stopPrice<limitPrice ?
  196.     ORDER_TYPE_BUY_STOP_LIMIT: ORDER_TYPE_SELL_STOP_LIMIT;
  197.  
  198.   Trade.SetDeviationInPoints(MaxAllowedSlippage);
  199.   Trade.SetExpertMagicNumber(magic);
  200.  
  201.   ENUM_ORDER_TYPE_TIME orderTime
  202.    = expiration==0? ORDER_TIME_GTC: ORDER_TIME_SPECIFIED;
  203.   if(Trade.OrderOpen(_Symbol,orderType,lots,limitPrice,stopPrice,sl,tp,
  204.         orderTime,expiration,entryName)) {
  205.     return Trade.ResultOrder();
  206.   }
  207.  
  208.   PrintLastError("MakeOrderStopLimit");
  209.   return 0;
  210. }
  211. //---------------------------------------------------------------------------
  212. //発注済オーダーのStoplossとTakeprofitの変更
  213. bool ModifyOrderSlTp(TICKET ticket, double sl, double tp) export
  214. {
  215.   bool res=Trade.PositionModify(ticket, sl, tp);
  216.   if(!res) PrintLastError("ModifyOrderSlTp");
  217.   return res;
  218. }
  219. //---------------------------------------------------------------------------
  220. //発注済予約注文の取消
  221. bool WithdrawOrder(TICKET ticket, color orderColor) export
  222. {
  223.   // ※ MT5 では、orderColor は使われない
  224.   bool res = Trade.OrderDelete(ticket);
  225.   if(!res) PrintLastError("WithdrawOrder");
  226.   return res;
  227. }
  228. //---------------------------------------------------------------------------
  229. //注文の決済
  230. bool CheckoutOrder(OP orderType, TICKET orderTicket, double orderLots) export
  231. {
  232.   // ※ MT5 では、orderType は使われない
  233.   uint startTick = GetTickCount();
  234.   for(int retry=0; retry<ORDER_RETRY; retry++) {
  235.     if(Trade.PositionClosePartial(orderTicket,orderLots,MaxAllowedSlippage)) {
  236.       //NetProfit += Trade.ResultProfit() + Trade.ResultCommission() + Trade.ResultSwap();
  237.       return true;
  238.     }
  239.     if(GetTickCount()-startTick>=ORDER_RETRY_DURATION)
  240.       break; // タイムオーバー
  241.     Sleep(ORDER_RETRY_SLEEP);
  242.   }
  243.   PrintLastError("CheckoutOrder");
  244.   return false ;
  245. }
  246. //---------------------------------------------------------------------------
  247.  
  248.   struct OBJECT_CHECKOUT {
  249.     TICKET Ticket;
  250.     double Profit;
  251.     OBJECT_CHECKOUT() {
  252.       Ticket = -1 ;
  253.       Profit = 0.0 ;
  254.     }
  255.     OBJECT_CHECKOUT(const OBJECT_CHECKOUT &lhs) {
  256.       Ticket = lhs.Ticket ;
  257.       Profit = lhs.Profit ;
  258.     }
  259.     OBJECT_CHECKOUT(TICKET Ticket_, double Profit_) {
  260.       Ticket = Ticket_ ;
  261.       Profit = Profit_ ;
  262.     }
  263.     bool operator <(const OBJECT_CHECKOUT &rhs) const {
  264.       return Profit < rhs.Profit ;
  265.     }
  266.   };
  267.  
  268. //注文の全決済
  269. bool CheckoutOrderAll(FLAG orderFlag, MAGIC magic, double lotsDenom) export
  270. {
  271.   int i;
  272.   bool result = true ;
  273.   CArrayObj *array = new CArrayObj();
  274.  
  275.   for(i = 0 ; i < PositionsTotal() ; i++){
  276.     if(PosInfo.SelectByIndex(i)) {
  277.       MAGIC posMagic = PosInfo.Magic();
  278.       ENUM_POSITION_TYPE posType = PosInfo.PositionType();
  279.       if( (posType==POSITION_TYPE_BUY&&(orderFlag&FLAG_BUY)!=0) ||
  280.           (posType==POSITION_TYPE_SELL&&(orderFlag&FLAG_SELL)!=0) ) {
  281.         if( PosInfo.Symbol() == Symbol() && (magic<0||magic==posMagic) ){
  282.           AddToArray(array,OBJECT_CHECKOUT(PosInfo.Ticket(),PosInfo.Profit()));
  283.         }
  284.       }
  285.     }
  286.   }
  287.   array.Sort(ARRAY_SORT_DESCEND); // 利益が多い順に並べ替える
  288.   for(i=0;i<array.Total();i++) {
  289.     CSortable<OBJECT_CHECKOUT> *node = (CSortable<OBJECT_CHECKOUT>*)array.At(i);
  290.     if(PosInfo.SelectByTicket(node.v.Ticket)) {
  291.       if(!CheckoutOrder(PosInfo.Type(),PosInfo.Ticket(),AdjustMarketLots(PosInfo.Volume()/lotsDenom))) {
  292.         result = false ; break;
  293.       }
  294.     }
  295.   }
  296.   delete array ;
  297.   return result ;
  298. }
  299. //---------------------------------------------------------------------------
  300. //時間動作制御(戻り値: true=アクティブ時間, false=オフタイム)
  301. bool ControlTimeAction(
  302.   datetime TimeTick, datetime TimeStart, datetime TimeEnd,
  303.   datetime &NextStartTime, MAGIC magic, ENUM_TIMEACT TimeAction) export
  304. {
  305.   MqlDateTime mqlTick, mqlStart, mqlEnd ;
  306.   TimeToStruct(TimeTick, mqlTick);
  307.   TimeToStruct(TimeStart, mqlStart);
  308.   TimeToStruct(TimeEnd, mqlEnd);
  309.  
  310.   // 活動時間帯のチェック
  311.   int ct = mqlTick.hour*60 + mqlTick.min ;
  312.   int st = mqlStart.hour*60 + mqlStart.min ;
  313.   int et = mqlEnd.hour*60 + mqlEnd.min ;
  314.   if(et<=st) {
  315.     if(st<=ct) et=24*60;
  316.     if(ct<=et) st=0;
  317.   }
  318.   bool activeTime = st <= ct && ct <= et ;
  319.  
  320.   bool isActivated = NextStartTime<TimeTick ;
  321.  
  322.   // 現在活動時間帯
  323.   if(activeTime) {
  324.     if(!isActivated)
  325.       NextStartTime = TimeTick ; // 現在時間を開始時間切り上げて完了
  326.     return true ;
  327.   }
  328.  
  329.   // 活動時間を次の時間にセットする
  330.   MqlDateTime mqlNextStart = mqlTick ;
  331.   mqlNextStart.hour = mqlStart.hour ;
  332.   mqlNextStart.min = mqlStart.min ;
  333.   mqlNextStart.sec = 0 ;
  334.   datetime timNextStart = StructToTime(mqlNextStart) ;
  335.   while(timNextStart<TimeTick)  timNextStart += 24*60*60 ;
  336.   NextStartTime = timNextStart ;
  337.  
  338.   // 次の開始までの秒数
  339.   datetime timOff = NextStartTime - TimeTick ;
  340.  
  341.   FLAG orderFlag = AlreadyOrdered(FLAG_SELL|FLAG_BUY, magic);
  342.  
  343.   STATUS status_long, status_short;
  344.   double total=0.0;
  345.  
  346.   switch(TimeAction) {
  347.     case TIMEACT_NONE:
  348.       // None
  349.       break;
  350.     case TIMEACT_FORCE_CLOSE_ALL:
  351.       // Force Close All positions
  352.       if(orderFlag!=0)
  353.         CheckoutOrderAll(orderFlag, magic, 1.0);
  354.       break;
  355.     case TIMEACT_FORCE_CLOSE_LONG:
  356.       // Force Close Long positions
  357.       if((orderFlag&FLAG_BUY)!=0)
  358.         CheckoutOrderAll(FLAG_BUY, magic, 1.0);
  359.       break;
  360.     case TIMEACT_FORCE_CLOSE_SHORT:
  361.       // Force Close Short positions
  362.       if((orderFlag&FLAG_SELL)!=0)
  363.         CheckoutOrderAll(FLAG_SELL, magic, 1.0);
  364.       break;
  365.     case TIMEACT_SOFT_CLOSE_ALL:
  366.       // Close All positions if profits are Positive
  367.       if(orderFlag!=0) {
  368.         CheckStatus(OP_BUY,magic,&status_long);
  369.         CheckStatus(OP_SELL,magic,&status_short);
  370.         total = status_long.GrossProfit+status_short.GrossProfit ;
  371.         if(total>0) {
  372.           CheckoutOrderAll(orderFlag, magic, 1.0);
  373.         }
  374.       }
  375.       break;
  376.     case TIMEACT_SOFT_CLOSE_LONG:
  377.       // Close Long positions if profits are Positive
  378.       if((orderFlag&FLAG_BUY)!=0) {
  379.         CheckStatus(OP_BUY,magic,&status_long);
  380.         total=status_long.GrossProfit;
  381.         if(total>0) {
  382.           CheckoutOrderAll(FLAG_BUY, magic, 1.0);
  383.         }
  384.       }
  385.       break;
  386.     case TIMEACT_SOFT_CLOSE_SHORT:
  387.       // Close Short positions if profits are Positive
  388.       if((orderFlag&FLAG_SELL)!=0) {
  389.         CheckStatus(OP_SELL,magic,&status_short);
  390.         total=status_short.GrossProfit;
  391.         if(total>0) {
  392.           CheckoutOrderAll(FLAG_SELL, magic, 1.0);
  393.         }
  394.       }
  395.       break;
  396.   }
  397.  
  398.   return false ;
  399. }
  400. //---------------------------------------------------------------------------
  401. //000,000,000表示
  402. string DoubleToAmount(double inputdata, int dig) export
  403. {
  404.   string textOrg = DoubleToString(inputdata,dig);
  405.   int lnOrg = StringLen(textOrg) ;
  406.   if(!lnOrg) return "" ;
  407.   int periodPos = StringFind(textOrg,".");
  408.   string textRes="";
  409.   int beg=0, lnHead = periodPos>=0 ? periodPos : lnOrg ;
  410.   StringReserve(textRes,lnHead+(lnHead+2)/3+1);
  411.   if(textOrg[0]=='-') { textRes="-"; beg++ ; } // マイナス損益
  412.   int lnRem = lnHead-beg ;
  413.   int first = lnRem%3;
  414.   if(!first&&lnRem>=3) first=3 ;
  415.   if(first>0) {
  416.     textRes+=StringSubstr(textOrg,beg,first);
  417.     for(int i=first;i<lnRem;i+=3) // 三桁区切り
  418.       textRes+=","+StringSubstr(textOrg,beg+i,3);
  419.   }
  420.   if(periodPos>=0)
  421.     return textRes+StringSubstr(textOrg,periodPos);
  422.   return textRes;
  423. }
  424. //---------------------------------------------------------------------------
  425.  
Tags: Mt5
Advertisement
Add Comment
Please, Sign In to add comment