エキスパート: トレーダーのためのMQL5プログラミング - 書籍からのソースコード。第7部 - ページ 2

 
Denis Kirichenko #:

一般的に、教科書の場合は括弧 書きで書くのがよいだろう:

ドギーは任意の演算の記号を意味し、@=の形の演算子はすべて、演算が実行される前に完全にカウントされた右オペランド上で常に実行される。これについては第2部の「修正操作」で説明する。

マージン計算ファイルはパート6で説明されるが、そこでは前のパートがマスターされていることが前提となる。この本の終盤になるにつれて複雑さが増していきます。私はそのことに異論はないので、過去のセクションの大きな概念や原則を、次のセクションから参照するようにしました。そこでは、(記憶をリフレッシュするために)積み木としてそれらが使われていますが、そのような小さなことには使われていません。

 
Stanislav Korotky #:

......この本の終盤になるにつれて複雑さが増していく。それに異論はない。だから、過去のセクションで出てきた大きな概念や原則については、(記憶をリフレッシュするために)次のセクションの構成要素として使われているところを参照するようにしたが、そのような小さなことについてはそうしなかった。

スタニスラフ、私はあなたと違ってプログラミングのレベルは控えめです。デバッガでチェックしやすいようにコードを書くようにしています。だから三項演算子はあまり使わない。使うとしても括弧と一緒に使うし...。三項演算子をいくつも組み合わせて書くような巧みな人もいる。これは私の同僚fxsaberの マクロ・プログラミング・スタイルに近いものだ。おそらく、どんなアプローチにも生きる権利がある。そしてそれはもう好みの問題なのだが...。

チュートリアルには大きな敬意と尊敬を表します!興味深いことがドキュメンテーションよりも詳しく説明されています。

 
Aleksandr Slavskii #:

というのも、ボリュームが3つ以上ある場合、結局マージンが正しくカウントされないからだ。

10枚の証拠金計算

チェック用のスクリプトを添付してください。出来高に関係なく、標準機能と一致します。

 
Denis Kirichenko #:

そしてコンパイラーは怒っている:

おそらくコンパイラの何かが変わったのだろう。この本が発売された時点では、デモンストレーションのために意図的にイレギュラーな処理をした場合を除き、すべてのソースは警告もエラーもなくコンパイルされていた。

 
Denis Kirichenko #:

デバッガーでチェックしやすいようにコードを書くようにしている。だから三項演算子はあまり使わない。使うとしても括弧と一緒に使うし......。

そうだね。私も、単純なケースを除いてはこのルールを守っています。コードの読みやすさは個々に扱われますが、通常は「すべてを1行にまとめる」アプローチと「各トークンを別々の行にまとめる」アプローチの間の「黄金平均」を探します。括弧も同様です。ソフトウェア会社には通常、ソースコードのレイアウトに関するルールがある。

 
経済カレンダーの読み込みとCSVへのエクスポートに関するバグフィックスと改善がコード ベースで公開された。具体的には、ソートされた大きな配列(通常MQL5カレンダーAPIから受け取る)の場合のソートアルゴリズムが修正され、スローダウンやスタックオーバーフローがなくなりました。
Economic Calendar CSV
Economic Calendar CSV
  • www.mql5.com
This script saves a predefined set of economic events from the MetaTrader's built-in economic calendar into CSV file.
 
Stanislav Korotky #:

検証用のスクリプトを添付してください。出来高に関係なく、標準機能と一致しています。

やれやれ。このメッセージに気づかなかったなんて。なんてこった。

実は、私の場合は何も変わっていない。

Metaquotサーバー、ターミナルバージョン4420。

コードはこんな感じ。

#include "MarginProfitMeter.mqh"
//+------------------------------------------------------------------+
int OnInit(void)
  {
   EventSetTimer(1);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
void OnTimer()
  {
   double margin = 0;
   double volume = 10;
   ENUM_ORDER_TYPE type = ORDER_TYPE_BUY;
   double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   if(_OrderCalcMargin(type, _Symbol, volume, price, margin))
      Print("Symbol ", _Symbol, "; volume ", volume, "; MarginProfitMeter margin = ", margin);

   margin = 0;
   if(OrderCalcMargin(type, _Symbol, volume, price, margin))
      Print("Symbol ", _Symbol, "; volume ", volume, "; OrderCalcMargin margin = ", margin);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   EventKillTimer();
  }
//+------------------------------------------------------------------+

結果はこうだ。

18:53:40.877    11 (EURUSD,H1)  Symbol EURUSD; volume 10.0; MarginProfitMeter margin = 10421.6
18:53:40.877    11 (EURUSD,H1)  Symbol EURUSD; volume 10.0; OrderCalcMargin margin = 23264.8

誰かがカウントを間違えている。


私はnamespace MPMを間違って取り除いたのかもしれない。 それが何なのか、なぜ必要なのか分からないが、EAをコンパイルさせてくれなかった。

実際には、名前空間MPMの 行を削除し、その後に中括弧を付け、 OrderCalcMarginの名前を変更 し、アンダースコアを追加しただけです。

一般的に、ファイルはこの形式でコンパイルされました。これがエラーの可能性はありますか?

//+------------------------------------------------------------------+
//|MarginProfitMeter.mqh
//|Copyright (c) 2018-2022, Marketeer |.
//|https://www.mql5.com/en/users/marketeer
//|| マージン、潜在的な利益/損失を計算する関数のセット。
//| ポイント値とカバー率。|
//+------------------------------------------------------------------+
// インジケータでは使用できない、組み込みの OrderCalcMargin のアナログ。
bool _OrderCalcMargin(const ENUM_ORDER_TYPE action, const string symbol,
                     double volume, double price, double &margin)
  {
   double marginInit, marginMain;
   MqlTick ticks;

// 与えられたパラメータをチェックする
   if((action != ORDER_TYPE_BUY && action != ORDER_TYPE_SELL) || volume < 0 || price < 0)
      return false;

// 計算式で使用されるすべてのプロパティを要求する。
   if(!SymbolInfoTick(symbol, ticks))
      return false;
   if(!SymbolInfoMarginRate(symbol, action, marginInit, marginMain))
      return false;
   const double contract = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   long leverage = AccountInfoInteger(ACCOUNT_LEVERAGE);
   if(volume == 0)
      volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   if(price == 0)
      price = action == ORDER_TYPE_BUY ? ticks.ask : ticks.bid;

   if(margin == DBL_MAX)
      marginInit = marginMain;
   margin = 0;

   const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);

   switch(m)
     {
      case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:
         leverage = 1;

      case SYMBOL_CALC_MODE_FOREX:
         margin = volume * contract / leverage * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFD:
         margin = volume * contract * price * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFDINDEX:
         margin = volume * contract * price * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE)
                  / SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE) * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFDLEVERAGE:
         margin = volume * contract * price / leverage * marginInit;
         break;

      case SYMBOL_CALC_MODE_EXCH_STOCKS:
      case SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX:
         if(price == 0)
            price = ticks.last;
         margin = volume * contract * price * marginInit;
         break;

      case SYMBOL_CALC_MODE_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
         margin = volume * SymbolInfoDouble(symbol, SYMBOL_MARGIN_INITIAL) * marginInit;
         break;
      default:
         PrintFormat("Unsupported symbol %s trade mode: %s", symbol, EnumToString(m));
     }

   string account = AccountInfoString(ACCOUNT_CURRENCY);
   string current = SymbolInfoString(symbol, SYMBOL_CURRENCY_MARGIN);
   if(current != account)
     {
      if(!_Convert(current, account, action == ORDER_TYPE_SELL, margin))
         return false;
     }

   return true;
  }

// 「現在の」通貨と「口座」通貨の単一ビルドで利用可能なシンボルを検索する。
int _FindExchangeRate(const string current, const string account, string &result)
  {
   for(int i = 0; i < SymbolsTotal(true); i++)
     {
      const string symbol = SymbolName(i, true);
      const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
      if(m == SYMBOL_CALC_MODE_FOREX || m == SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE)
        {
         string base = SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE);
         string profit = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);
         if(base == current && profit == account)
           {
            result = symbol;
            return +1;
           }
         else
            if(base == account && profit == current)
              {
               result = symbol;
               return -1;
              }
        }
     }
   return 0;
  }

// 指定したシンボルの過去のある時点でのレートを推定する
double GetHistoricPrice(const string symbol, const datetime moment, const bool ask)
  {
   const int offset = iBarShift(symbol, _Period, moment);
// NB:iCloseは、取引所シンボルのBidの代わりにLast priceを保持することができる。
// これを高速に処理する方法はない。
   return iClose(symbol, _Period, offset) +
          (ask ? iSpread(symbol, _Period, offset) * SymbolInfoDouble(symbol, SYMBOL_POINT) : 0);
  }

// 現在」の金額を「口座」の金額に変換する。
bool _Convert(const string current, const string account,
             const bool ask, double &margin, const datetime moment = 0)
  {
   string rate;
   int dir = _FindExchangeRate(current, account, rate);
   if(dir == +1)
     {
      margin *= moment == 0 ?
                SymbolInfoDouble(rate, ask ? SYMBOL_BID : SYMBOL_ASK) :
                GetHistoricPrice(rate, moment, ask);
     }
   else
      if(dir == -1)
        {
         margin /= moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);
        }
      else
        {
         static bool once = false;
         if(!once)
           {
            Print("Can't convert ", current, " -> ", account);
            once = true;
           }
        }
   return true;
  }

// 特定のシンボルのポイント値(口座通貨)を返す
double PointValue(const string symbol, const bool ask = false, const datetime moment = 0)
  {
   const double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   const double contract = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
   double result = 0;

   switch(m)
     {
      case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:
      case SYMBOL_CALC_MODE_FOREX:
      case SYMBOL_CALC_MODE_CFD:
      case SYMBOL_CALC_MODE_CFDINDEX:
      case SYMBOL_CALC_MODE_CFDLEVERAGE:
      case SYMBOL_CALC_MODE_EXCH_STOCKS:
      case SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX:
         result = point * contract;
         break;

      case SYMBOL_CALC_MODE_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
         result = point * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
         break;
      default:
         PrintFormat("Unsupported symbol %s trade mode: %s", symbol, EnumToString(m));
     }

   string account = AccountInfoString(ACCOUNT_CURRENCY);
   string current = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);

   if(current != account)
     {
      if(!_Convert(current, account, ask, result, moment))
         return 0;
     }

   return result;
  }
//+------------------------------------------------------------------+
 
Aleksandr Slavskii #:

コードは以下の通り。

結果は次のようになる。

誰かがカウントを間違えている。


2024年初頭(つまり、この本の執筆後)のビルド4150 -https://www.metatrader5.com/en/releasenotes/terminal/2342 に関するニュースに、こんな記述がある。

出来高別浮動証拠金

サーバー設定とシンボル仕様インターフェイスに、マージンの出来高依存性が追加された。

MQL5からこれらのプロパティにアクセスする方法は見つかりませんでした。

特定のブローカー/商品では、このフローティング・マージンの設定が有効になっていない可能性があります。

MetaTrader 5 build 4150: Trading report export and new machine learning methods in MQL5
MetaTrader 5 build 4150: Trading report export and new machine learning methods in MQL5
  • 2024.01.18
  • MetaQuotes
  • www.metatrader5.com
Added export of trading reports to HTML and PDF files. With this option, you can easily share your trading achievements with colleagues and investors. New export commands are available in the File menu and in the report menu. Added ability to save the current state of the Market Watch window to a CSV file. To do this, select Export in the...
 
Stanislav Korotky #:

サーバー設定とシンボル指定インターフェイスにボリュームマージン依存性を追加。

MQL5からこれらのプロパティにアクセスする方法が見つかりません。

また、検索しても見つかりませんでした)
私の頭の中のバグかと思いましたが、そうではないことがわかりました。
ありがとう。
 

レナト・ファトフーリン

MQL5からこれらのプロパティを取得する機能を追加する予定はありますか?

取引、自動取引システム、取引戦略のテストに関するフォーラム

Expert Advisors: トレーダーのためのMQL5プログラミング - 本からのソースコード。パート7

スタニスラフKorotky、2024.11.23 20:26

2024年初頭(つまりこの本が書かれた後)のニュースで、ビルド4150 -https://www.metatrader5.com/en/releasenotes/terminal/2342。

出来高別浮動証拠金

サーバーの設定とシンボル指定のインターフェイスに、マージンのボリューム依存性が追加されていました。

私はMQL5からこれらのプロパティにアクセスする方法を見つけられませんでした。

特定のブローカー/商品では、このフローティング・マージン設定が有効になっていない可能性があります。