mql5言語の特徴、微妙なニュアンスとテクニック - ページ 208

 
mktr8591:

どうやら、私は取引状況を誤解していたようだ。

私のイメージでは、保留中の指値注文が複数の取引で執行されました。今までずっとライブ注文でぶら下がっていて、ORDER_TIME_SETUP フィールドが定数でなかった。最後の取引後、履歴に入りました。その瞬間、ORDER_TIME_SETUPは 定数化された。

それとも、そうでなかったのか?

ORDER_TIME_SETUP は常に定数である。履歴に入ると-ORDER_TIME_DONEが表示されました。

 
fxsaber:

ORDER_TIME_SETUP は常に定数である。履歴にヒットすると-ORDER_TIME_DONEが表示される。

ここで私は今、遅延リミットを設定しています。そして、手作業やスクリプトで変更し、ORDER_TIME_SETUPが 変化する。

私は何を間違えているのだろう?

 
Особенности языка mql5, тонкости и приёмы работы
Особенности языка mql5, тонкости и приёмы работы
  • 2020.04.09
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql5, примеры решения тех, или иных задач...
 
mktr8591:

ここで私は今、遅延リミッターを設定しています。その後、手動やスクリプトで変更すると、ORDER_TIME_SETUPが 変更されます。

私は何を間違えているのだろう?

設定した時間は変わりません。

 

確かにそうですね。でも、まったく思い出せなかった。バグだと思うんです。


fxsaber:

部分実行を繰り返すとどうなるのかわからない。

今、私は知っています - このブローカーでは(私は彼らのソフトウェアのバグに傾いている)、それはこれ以上変わりません。

 
// Возвращает снепшот котирования символа.
int QuotesSnapshot( const string Symb = NULL, const datetime From = 0 )
{    
  int Snapshot = INT_MAX;

  MqlTick Ticks[];
  
#define  DAY (24 * 3600)  
  const int Size = CopyTicksRange(Symb, Ticks, COPY_TICKS_INFO, From ? From * 1000 : SymbolInfoInteger(Symb, SYMBOL_TIME) / DAY * DAY * 1000);
#undef  DAY  
  
  for (int i = 1; i < Size; i++)
  {
    const int Interval = (int)(Ticks[i].time_msc - Ticks[i - 1].time_msc);
    
    if (Interval < Snapshot)
      Snapshot = Interval;
  }
  
  return(Snapshot);
}

チックの放送頻度を知っておくと便利なこともあります。

 

CloseBy取引は、2つの取引を発生させます。最初の取引(CloseByの最初のポジション)のスワップは、両方のポジションのスワップの合計を含んでいます。第2トレードのスワップは0円です。

クローズバイによりポジションの一部決済が行われた場合、オープンポジションの残りの部分はスワップが剥奪され、ゼロになります。


// Демонстрация работы со свопами во время частичного закрытия через CloseBy.

#define  REPORT_TESTER             // В тестере будут автоматически записываться отчеты
#define  REPORT_BROWSER            // Создание отчета с запуском браузера - требует разрешения DLL.
#include <Report.mqh> // https://www.mql5.com/ru/code/18801

#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun)
  {
    if (!OrderSelect(0, SELECT_BY_POS))
      FirstRun = OrderSend(_Symbol, OP_BUY, 100, Ask, 0, 0, 0);
    else if (OrderSwap())
    {
      const TICKET_TYPE Ticket = OrderTicket();
      
//      FirstRun = !(OrderCloseBy(OrderSend(_Symbol, OP_SELL, 0.01, OrderClosePrice(),0, 0, 0), Ticket) &&
      FirstRun = !(OrderCloseBy(Ticket, OrderSend(_Symbol, OP_SELL, 0.01, OrderClosePrice(),0, 0, 0)) &&
                   OrderSelect(0, SELECT_BY_POS) && OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0));      
    }    
  }    
}


結果


そのため、ロールオーバーを経たことのない最小のポジションには、巨大なスワップが存在する可能性があります。そして、ロールオーバーした大きなポジションのスワップはゼロ。

 

ロールオーバーの回数を計算する(最速のオプションではない)。

#define  DAY  (24 * 3600)
#define  WEEK (DAY * 7)

// Возврящает количество "четвергов" между двумя датами.
int GetAmountWeekDay( const datetime Begin, const datetime End, const int DayWeek = -1 )
{
  const datetime OffsetTime = (DayWeek - WEDNESDAY) * DAY;
  
  return((DayWeek != -1) ? (int)((End - OffsetTime) / WEEK - (Begin - OffsetTime) / WEEK) : 0);
}

// Возврящает количество рабочих дней между двумя датами.
int GetAmountWorkingDays( const datetime Begin, const datetime End )
{
  const int Res = (int)(End / DAY - Begin / DAY);
  
  return(Res ? Res - GetAmountWeekDay(Begin, End, SATURDAY) - GetAmountWeekDay(Begin, End, SUNDAY) : 0);
}

// Возвращает количество ролловеров (включая тройные) между двумя датами.
int GetRolloverAmounts( datetime TimeOpen, datetime TimeClose,
                        datetime RolloverTime = 0, const int Rollover3Days = WEDNESDAY )
{
  RolloverTime = RolloverTime % DAY;
  
  TimeOpen -= RolloverTime;
  TimeClose -= RolloverTime;
  
  const int Res = GetAmountWorkingDays(TimeOpen, TimeClose);
  
  return(Res ? Res + (GetAmountWeekDay(TimeOpen, TimeClose, Rollover3Days) << 1) : 0);
}

#undef  WEEK
#undef  DAY


使用例

// Сравниваем реальные и вычисленные значения свопов.

#include <MT4Orders.mqh>

input datetime inRolloverTime = 0; // Время ролловера
input int inCount = 100; // Маскимальное количество распечаток

// Вычисляет своп закрытой позиции.
double CalcOrderSwap( const datetime RolloverTime = 0 )
{
  return(((OrderType() <= OP_SELL) &&
          (SymbolInfoInteger(OrderSymbol(), SYMBOL_SWAP_MODE) == SYMBOL_SWAP_MODE_POINTS))
             // https://www.mql5.com/ru/forum/170952/page208#comment_24667438
           ? GetRolloverAmounts(OrderOpenTime(), OrderCloseTime(), RolloverTime,
             (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_SWAP_ROLLOVER3DAYS)) *
             SymbolInfoDouble(OrderSymbol(), OrderType() ? SYMBOL_SWAP_SHORT : SYMBOL_SWAP_LONG) *
             SymbolInfoDouble(OrderSymbol(), SYMBOL_TRADE_TICK_VALUE) *
             OrderLots()
           : 0);
}

#define  TOSTRING(A) " " + #A + " = " + (string)(A)

void OnStart()
{  
  for (int i = OrdersHistoryTotal() - 1, Count = 0; (i >= 0) && (Count < inCount); i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && OrderSwap())
    {
      OrderPrint();
      Print((string)Count++ + TOSTRING(OrderSwap()) + TOSTRING(CalcOrderSwap(inRolloverTime)) + "\n");
    }
}


結果

#2122237 2021.09.09 23:09:15.512 sell 0.18 GBPCAD 1.75119 0.00000 1.75286 2021.09.10 04:27:40.506 1.75286 -0.84 -0.80 -20.07 7;[0] 7
97 OrderSwap() = -0.8 CalcOrderSwap(inRolloverTime) = -0.8048844238618312
 
fxsaber #:

CloseBy取引は、2つの取引を発生させます。最初の取引(CloseByの最初のポジション)のスワップは、両方のポジションのスワップの合計を含んでいます。第2トレードのスワップは0円です。

クローズバイによりポジションの一部決済が行われた場合、残りの未決済ポジションはスワップが奪われ、ゼロになります。

...

そのため、ロールオーバーを経たことのない最小限のポジションには、巨大なスワップが存在する可能性があります。そして、ロールオーバーした大口ポジションのスワップはゼロ。

驚きです。

四捨五入(1セントも減らさない、足さないように)のせいでしょうか?

それとも、めったに使わない操作だから関係ない?

 
Andrey Khatimlianskii #:

驚きです。

四捨五入(1セントも減らさない、足さないように)のせいでしょうか?

部分的なクローズ(フルオーダーロットではなくオーダークローズ)は、それに応じてスワップが消耗するので、絶対にダメです。

それとも、めったに使わない操作だから関係ない?

シナリオはあまり考えられていないと思います。

理由: