mql4でOnTradeTransaction()の代わりになるものは何ですか? - ページ 8

 
Vitaly Muzichenko:

解決策は簡単で、履歴を変更するための別のチェックを導入することです。そうすれば、何も失われることなく、100%機能するようになるのです。

これは不完全な OnTrade() として使用することもできます。

void OnTrade()
 {
  ...
 }

static __OTotal = -1;
static __HTotal = -1;
int OT=OrdersTotal();
int HT=OrdersHistoryTotal();
  if(OT!=__OTotal || HT!=__HTotal) // если изменилось - выполняем
   {
     OnTrade(); // здесь дёргаем текущую ситуацию на счёте и заполняем структуры
     __OTotal=OrdersTotal(); // запомним текущее количество
     __HTotal=OrdersHistoryTotal(); // запомним количество в истории
   }
 
Vitaly Muzichenko:

頭が悪いんでしょうね(笑)。

どのように適用すればよいのでしょうか?

今日、数年ぶりに発見したのですが、以前からあったのかもしれませんが、気がつかなかっただけです。


ハッシュサム計算の話ですが、ハッシュサムの値に文字名を追加する方法、文字名に含まれる文字コードの値を計算する方法です。

 
Vitaly Muzichenko:

解決策は簡単で、別の履歴変更チェックを導入すれば、何も失われることなく、100%機能します。

以下、拙稿3号から抜粋してご紹介します。

-------

ここでは、構造の一部であるハッシュ量にもっと注目しましょう。
アカウントで何が変更されたかを正確に判断するには、注文とポジションの数を知るだけでは不十分です。 保留注文が削除されることがあり、この場合、アカウント内の注文とポジションの合計数が変更されます。でも...保留中の注文がトリガーされ、ポジションとなる場合があります。この場合、注文とポジションの合計金額は変わりません(ヘッジ口座とMQL4の場合)。 ポジション数は増えていますが、注文数は減っていますので、合計金額は変わりません。これは私たちには通用しません。

チケットについて考えてみましょう。 保留中の注文を追加/削除すると、口座のティック総量が変化します。保留中の注文をトリガーしても、口座のティック総量は変化しません。

総量を見てみよう。お客様が保留中の注文を 発注または削除 した - 口座の合計金額が変更されました。当社が注文を発注または決済、またはポジションを変更した - 口座の合計金額が変更されました。適しているように見えますが、もう一度言いますが、保留中の注文を有効にしても、総量は変わりません。

そこで、もう1つのポジションのプロパティである その変化時間をミリ秒単位で見てみましょう。新しいポジションを開くとポジション変化時間の合計が変わり、部分的に閉じることでポジション変化時間が変わり、ネッティング口座に数量を追加するとポジション変化時間の合計が変わることになります。

勘定科目の変更箇所を正確に把握する方法として適しているものはどれか。チケット+ポジションチェンジの時間。 確認しよう。

  • ポジション開設 - チケット金額変更 + ポジション変更時間変更 - 変更あり
  • ポジションを決済しました - 刻み幅が変更されました - 変更が あります。
  • 保留中の注文を発注 - チケット ポジション変更時刻が変更 されていない -- 変更あり
  • 保留中の注文を削除 - チケット金額変更 + ポジション変更時間金額変更なし - 変更 あり
  • 保留注文発動 - チケット金額変更なし+ポジション変更時間帯金額変更あり - - 変更あり
  • 一部ポジションクローズ - チケット金額変更 + ポジション変更時間変更 - - 変更あり
  • ポジションにボリュームを追加 - チケット金額変更なし+ポジション変更時間変更 - - 変更あり
したがって、ハッシュサムには、チケット+ポジションの変化時間(ミリ秒)を使用 することになります。

しかし、ここではハッシュサムに記号を付けなかった。そのような前例はなかった。でも、チェック履歴と連動しているんです。したがって - エラーなしで動作するはずです。しかし、今度チェックしてみます。

Библиотека для простого и быстрого создания программ для MetaTrader (Часть III): Коллекция рыночных ордеров и позиций, поиск и фильтрация
Библиотека для простого и быстрого создания программ для MetaTrader (Часть III): Коллекция рыночных ордеров и позиций, поиск и фильтрация
  • www.mql5.com
В первой части данного цикла статей мы начали создавать большую кроссплатформенную библиотеку, целью которой является облегчение создания программ для платформы MetaTrader 5 и MetaTrader 4. Во второй части продолжили развитие библиотеки и сделали коллекцию исторических ордеров и сделок. В данной части повествования создадим класс для удобного...
 
Vitaly Muzichenko:

解決策は簡単で、別の履歴変更チェックを導入すれば、何も失われることなく、100%機能するようになります。

そして、はい、そうなります。未決済注文の件数に変化がない場合は、履歴の数字が変化します。(保留中の注文は気にしない。使わない) また、たった1つのイベントをキャッチするために、1日中通う 必要もない。

また、ユーザーがテキストメッセージを受信している場合は、端末に履歴を表示する代わりに、先月だけのすべてのそれを表示することにしました、それは致命的ではありませんが、すべての注文を試していると追加のチェックになります。

良い解決策になりそうです。そして、取引口座と端末という、今あるもの以外には何も言及しない。

 
Artyom Trishkin:

以下、拙稿3号から抜粋してご紹介します。

-------

構造の一部であるハッシュ量について詳しく説明しよう。
この変化を正確に判断するためには、口座内で変化した注文やポジションの量を知るだけでは不十分です。 保留注文が削除されることがあり、この場合、口座内の注文やポジションの総量が変化することになります。でも...保留中の注文がトリガーされ、ポジションとなる場合があります。この場合、注文とポジションの合計金額は変わりません(ヘッジ口座とMQL4の場合)。 ポジション数は増えても、注文数は減るので、合計金額は変わりません。これは私たちには通用しません。

チケットを検討する。保留中の注文を追加/削除すると、アカウントのチケットの合計金額が変更されます。保留中の注文をトリガーしても、アカウントのチケットの合計金額は変更されません。

総量を考える。保留中の注文を 発注または削除 した - 口座の総数量の変更、オープン、クローズ、またはポジションの変更 - 口座の総数量の変更。適しているように見えますが、もう一度言いますが、保留中の注文を有効にしても、総量は変わりません。

そこで、もう1つのポジションのプロパティである その変化時間をミリ秒単位で見てみましょう。新しいポジションを開くとポジション変化時間の合計が変わり、部分的に閉じることでポジション変化時間が変わり、ネッティング口座に量を追加することでポジション変化時間の合計が変わります。

勘定科目の変更箇所を正確に把握する方法として適しているものはどれか。チケット+ポジションチェンジの時間。 確認しよう。

  • ポジション開設 - チケット変更額+ ポジション変更時間分- 変更あり
  • ポジションを決済しました - 刻み幅が変更されました - 変更が あります。
  • 保留中の注文を発注 - チケット ポジション変更時刻が変更 されていない -- 変更あり
  • 保留中の注文を削除 - チケット金額変更 + ポジション変更時間金額変更なし - 変更 あり
  • 保留注文発動 - チケット金額変更なし+ポジション変更時間帯金額変更あり - - 変更あり
  • 一部ポジションクローズ - チケット金額変更 + ポジション変更時間変更 - - 変更あり
  • ポジションにボリュームを追加 - チケット金額変更なし+ポジション変更時間変更 - - 変更あり
したがって、ハッシュサムには、チケット+ポジションの変化時間(ミリ秒)を使用することになります。

しかし、ここではハッシュサムに記号を付けなかった。そのような前例はなかった。でも、チェック履歴と連動しているんです。したがって - エラーなしで動作するはずです。しかし、今度チェックしてみます。

ファットソリューション、そのようなバリアントはまだ必要ありません。

ありがとうございました。

 
Vitaly Muzichenko:

脂肪の決定、そのオプションはまだ必要ありません。

ありがとうございました。

"大胆 "なのは、ローカルソリューションのためではなく、OnTradeXXXXの本格的なリプレイスの1パーツとして作られたからです。歴史のある作品が増えましたね。

そして、これは大きな利点です。プログラム内のあらゆる注文とポジションの検索とソートのためのデータが準備されています(プログラムのニーズを満たすために注文とポジションを再度検索する必要はありません - すべてがすでにリストに含まれています)。もう一つの利点は、上記のバージョンではできないことですが、MQL4ではどの順序でポジションが発生したかをプログラムが知っていることです。

繰り返しになりますが、図書館は、時間とお金が有り余っている人が、自分で簡単にできるようにするために作られたものです。もちろん、何も主張しませんよ :)

 
Aleksandr Volotko:

そして、その通りになりました。未決済注文の数が変化しない場合は、履歴の数字が変化します。(私は保留中の注文は気にしません。使いません。)そして、たった一つのイベントをキャッチするために、一日中注文を調べておばあさんを困らせる 必要はないのです。

また、ユーザーがテキストメッセージを受信している場合は、端末に履歴を表示する代わりに、先月だけのすべてのそれを表示することにしました、それは致命的ではありませんが、すべての注文を試していると追加のチェックになります。

良い解決策になりそうです。取引口座と端末があれば、何にも縛られることなく、自分の持っているものだけを使うことができます。

丸一日を通過しないために、あなたは、変更につながることができる条件、オープン、ポジションを閉じ、すなわちエキスパート-アドバイザが開くために使用する価格を達成することに焦点を当てるときにのみ確認することができ、TP、SL。まあ、Expert Advisorのロジックにもよるけど、安いのはわかるでしょ。

 
Aleksey Mavrin:

一日中、ポジションの変更、オープン、クローズにつながる条件が満たされたときだけチェックすることができます。つまり、エキスパートアドバイザーがオープン、TP、SLに使用する価格の達成に集中するためです。そうですね、Expert Advisorのロジックにもよりますが、安いのはわかりますよね。

1つのEAで(1台のコンピュータ、1つの大陸で)取引される。もう一方は(別の大陸の別のコンピュータで)その機能を処理する。 解決策はすでに見つかっています。

 
fxsaber:

何か再現性のある例(取引履歴をポーリングせずに)を提示していただけるとありがたいです。

ここで出てきたのは(ここではオフトピックですが、ここで求められていたものです)。

ライブを切り取る。MT4との互換性なし(当然)、エラー処理なしなど。

取引は原始的で、買いでオープンし、SL/TPでクローズする。唯一のポイントは、OnTradeTransaction() と「サーバーをポーリングする」ことの比較の実証です。

私の場合、与えられたインターバルで合格するのに2.34秒と3.06秒を要しました。サーバー機能の負荷が低い(1ポジションのみ、マジコンやシンボルのチェックなし)ため、この差は小さい。実際のEAでは、その差はもっと大きくなります。シグナルを計算し、トレーリングストップを加えることで、その差は若干滑らかになりますが、これらは毎ティック行う必要はありません。私のATRはM1で計算されていますが、6時間足です(つまり、TFを拡大するスペースがあります)。そして、H3ではトレーリングとブレークイーブンが計算されます。すべては戦略次第です。

// Test OnTradeTransaction.mqh
#property version   "1.00"
#property copyright "(c)2020 Edgar Akhmadeev"
#property link      "https://www.mql5.com/en/users/dali"
// 2020.01.27

//      Primitive expert to test OnTradeTransaction().
//      BUY only one position a time. There's no any signals.
//      Try OHLC M1 EURUSD 2016.12.19-2018.04.14 (bull trend) with default SL/TP.



//#define TESTER



#define  MT4_TICKET_TYPE
#include <MT4Orders.mqh>
#include <mql4_to_mql5.mqh>



struct PosInfoBase {
        double                  price, sl, tp;
        datetime                time;
        int                     ticket;
        ENUM_ORDER_TYPE 	 type;

        #ifndef  TESTER
                int             mn;
                string          sym;
        #endif 
};

struct PosInfo {
        PosInfoBase             base;
        int                     ticket;
};



input int       SL              = 6;
input int       TP              = 900;



MqlTick         tick;
PosInfo         posInfo         = { 0 };



#ifdef  TESTER

//*************************************************************************************************************
void 
OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) {
        if (trans.type == TRADE_TRANSACTION_ORDER_DELETE && trans.order_state == ORDER_STATE_PLACED) {
                // No money
                //errFatal = true;
                return;
        }
        
        static long lastTick;

        if (trans.type == TRADE_TRANSACTION_DEAL_ADD && trans.order_state == ORDER_STATE_STARTED) {
                // Open on market step1, SL/Order triggered step1, SL/Order triggered step4
                
                if (!HistoryDealSelect(trans.deal)) {
                        //errFatal = true;
                        return;
                }
                
                ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(trans.deal, DEAL_ENTRY);
                if (entry != DEAL_ENTRY_OUT)
                        return;
                
                ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(trans.deal, DEAL_REASON);
                if (reason != DEAL_REASON_SL && reason != DEAL_REASON_TP)
                        return;
                
                if (lastTick == tick.time_msc)
                        return;

                posInfo.base.ticket = 0;
                InitPos();

                lastTick = tick.time_msc;
                return;
        }
}



#else // TESTER



//*************************************************************************************************************
bool
Support() {
        posInfo.base.ticket = 0;
        
        int cnt = PosTotal();
        if (cnt > 1)
                return false;
        
        PosInfo _posInfo;
        
        if (cnt == 0)
                _posInfo.base.ticket = 0;
        else {
                PosInfoFill(_posInfo);
                _posInfo.ticket = _posInfo.base.ticket;
        }

        //-------------------------------------------------------------------------------------------------------------
        // Position: process
        
        if (_posInfo.base.ticket != 0 && posInfo.ticket != 0 && _posInfo.base.ticket == posInfo.ticket) {
                // Ничего не произошло, та же позиция
                
                posInfo.base.ticket = _posInfo.base.ticket;
                posInfo.base.time = _posInfo.base.time;
                //posInfo.base.price = _posInfo.base.price;
                posInfo.base.sl = _posInfo.base.sl;
                posInfo.base.tp = _posInfo.base.tp;
        }

        //-------------------------------------------------------------------------------------------------------------
        // Инициализация новой позиции
        
        if (posInfo.base.ticket > 0)
                return true;
        
        return InitPos();
}

#endif // TESTER



//*************************************************************************************************************
bool
InitPos() {
        if (!SymbolInfoTick(_Symbol, tick))
                return false;
        
        posInfo.base.type = ORDER_TYPE_BUY;
        posInfo.base.sl = NormalizeDouble(tick.bid - SL * Point, Digits); 
        posInfo.base.tp = NormalizeDouble(tick.bid + TP * Point, Digits);       

        ResetLastError();
        int order = OrderSend(_Symbol, posInfo.base.type, 0.01, tick.ask, 99, posInfo.base.sl, posInfo.base.tp); 
        if (order < 0)
                return false;
        
        if (!OrderSelect(order, SELECT_BY_TICKET))
                return false;

        posInfo.base.price = OrderOpenPrice();
        posInfo.ticket = posInfo.base.ticket = order;
        posInfo.base.time = tick.time;
        return true;
}



//*************************************************************************************************************
int
PosTotal() {
        int posTotal = OrdersTotal();
        int cnt = 0;
        for (int i = posTotal - 1; i >= 0; --i) {
                if (!OrderSelect(i, SELECT_BY_POS)) {
                        //errFatal = true;
                        return -1;
                }

                if (OrderType() > OP_SELL)
                        continue;

                /*
                #ifndef TESTER
                        if (OrderMagicNumber() != MagicNum)
                                continue;
                        if (OrderSymbol() != symInfo.sym)
                                continue;
                #endif 
                */
                        
                ++cnt;
        } // for
        
        return cnt;
}


        
//*************************************************************************************************************
void
PosInfoFill(PosInfo& _posInfo) {
        ZeroMemory(_posInfo);

        _posInfo.base.ticket = (int)PositionGetInteger(POSITION_TICKET);
        _posInfo.base.type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE);
        _posInfo.base.price = PositionGetDouble(POSITION_PRICE_OPEN);
        _posInfo.base.time = (datetime)PositionGetInteger(POSITION_TIME);
        _posInfo.base.sl = PositionGetDouble(POSITION_SL);
        _posInfo.base.tp = PositionGetDouble(POSITION_TP);

        #ifndef  TESTER
                _posInfo.base.mn = (int)PositionGetInteger(POSITION_MAGIC);
                _posInfo.base.sym = PositionGetString(POSITION_SYMBOL);
        #endif 
}



//*************************************************************************************************************
void 
OnTick() {
        ResetLastError();
        if (!SymbolInfoTick(_Symbol, tick)) {
                int LE = GetLastError();
                //errFatal = true;
                return;
        }
        
        #ifdef  TESTER

                if (posInfo.base.ticket > 0)
                        return;
                
                if (!InitPos()) {
                        //errFatal = true;
                        return;
                }

        #else  // TESTER
                
                if (!Support()) {
                        //errFatal = true;
                        return;
                }
        
        #endif // TESTER
}



//*************************************************************************************************************
int 
OnInit() {
        return INIT_SUCCEEDED;
}



//*************************************************************************************************************
void 
OnDeinit(const int reason) {
}
 
prostotrader:

絶望的なまでに時代に取り残されている!

これらのイベントは、ずっと保証 されているのです

OnTradeTransaction() でイベントが発生し、その後に何らかのアクションを実行する必要があるが、そのアクションを最初に実行しようとしたときにエラーが発生したとする。どうすればいいのか?明らかに、それは繰り返されなければならず、そのためには、これらのアクションを繰り返す必要性についてのデータをどこかに保存する必要があります - ほとんどの場合、このデータはExpert Advisorの通常のグローバル変数または静的関数に保存されています。そして突然、端末を再起動しなければならなくなった...。データが消えてしまう。

そして、現状と歴史を分析すると......何もかもがうまくいかなくなる。