PLOについての興味深い見解 - ページ 8

 
fxsaber:

好きだからこうやって書いているんです。とはいえ、デバッグ時には本当にひどい目に遭います。


この表現でも

誰が何を返したのかがわかりにくい。もっと複雑なものでは(私はいつも練習しているのですが)本当に難しいです。

もし、2-3...5つの関数の実行結果を論理演算(または条件付き三項演算子)で結合したとする - githabかどこかで見たことがある、このコードで処理可能だ。

でも、この「いいもの」を12個も持っていたら...。無用の長物

 
Maxim Kuznetsov:

もちろん、私はmqlの開発者ではありません。

が、Cスイッチではかなり効率的なバイナリサーチを 生成し、不要なページングやキャッシュダンプを発生させない。そう、配列や構造体を使った間接的なアドレス指定よりも優れていることが多いのです。

開発者の方がどこかに書いておられましたが、ここにも同じような情報があります。

は、これしかありませんでした。

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

MQL5で発見した記事です。

スラバ, 2011.04.14 09:59

いいえ、残念ながらそうではありません。文字列型の場合のみ、 ...でなければさもなくば

switchで整数型を 使用することで、Analyzerのコードを数倍高速化することができます。


 
Igor Makanu:

でも、十数人なら...。imhoは、実用的ではありません。

小さな怪物。

  static bool VirtualOrderSelect( const TICKET_TYPE Index, const int Select, const int Pool = MODE_TRADES )
  {
    return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderSelect(Index, Select, Pool) :
           #ifdef  VIRTUAL_SNAPSHOT_REFRESHTIME
             VIRTUAL::SnapshotPtr ?
             #ifdef __MQL5__ // Выбор по тикету в MT5 - разнообразный набор вариантов.
               (Select == SELECT_BY_TICKET) ? ::OrderSelect(Index, Select, Pool) && VIRTUAL::SnapshotPtr.CopyOrder()
                                            :
             #endif // #ifdef __MQL5__
                                              ((((Index == INT_MIN) || (Index == INT_MAX)) && (Pool == MODE_TRADES) &&
                                               ::OrderSelect(Index, Select, Pool) &&
                                             #ifdef  VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder(true))
                                             #else // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder())
                                             #endif // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY #else
                                               || VIRTUAL::SnapshotPtr.OrderSelect(Index, Select, Pool))
                                  :
           #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
           #ifdef __MQL5__
             #ifdef __MT4ORDERS__
               ::OrderSelect(Index, Select, Pool)
             #else // __MT4ORDERS__
               false
             #endif // __MT4ORDERS__
           #else // __MQL5__
             ::OrderSelect(Index, Select, Pool)
           #endif // __MQL5__
           );
  }

論理的な操作により、マクロで設定を使い分ける際にも簡潔に書くことができます。でも、もちろんホラーです。

 
fxsaber:

論理演算により、マクロによる各種設定も簡潔に記述できます。でも、もちろんホラーです。

"目的は手段を正当化する "の例ですね。

頓珍漢な文体

 
fxsaber:

小さな怪物。

プレゼントされた馬の口を見てはいけない。しかし、ここでは他の人のコードの例をいくつか紹介します。これらのコードは、私に忘れられない数十分のデバッグ時間を与えてくれました。もしかしたら、誰かが自分のコードを認識するかもしれません。

      Res = (!FillingMode || (Type >= ORDER_FILLING_RETURN) || ((FillingMode & (Type + 1)) != Type + 1)) ?
            (((ExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE) || (ExeMode == SYMBOL_TRADE_EXECUTION_INSTANT)) ?
             ORDER_FILLING_RETURN : ((FillingMode == SYMBOL_FILLING_IOC) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK)) :
            (ENUM_ORDER_TYPE_FILLING)Type;
    return((arrow_color == INT_MAX) ? (MT4ORDERS::NewOrderCheck() ? 0 : -1) :
           ((((int)arrow_color != INT_MIN) || MT4ORDERS::NewOrderCheck()) &&
            MT4ORDERS::OrderSend(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) ?
            (MT4ORDERS::IsHedging ? (long)MT4ORDERS::LastTradeResult.order : // PositionID == Result.order - особенность MT5-Hedge
             ((MT4ORDERS::LastTradeRequest.action == TRADE_ACTION_DEAL) ?
              (MT4ORDERS::IsTester ? (_B2(::PositionSelect(MT4ORDERS::LastTradeRequest.symbol)) ? PositionGetInteger(POSITION_TICKET) : 0) :
                                      // HistoryDealSelect в MT4ORDERS::OrderSend
                                      ::HistoryDealGetInteger(MT4ORDERS::LastTradeResult.deal, DEAL_POSITION_ID)) :
              (long)MT4ORDERS::LastTradeResult.order)) : -1));

そのように書くのが簡単かどうかはわかりませんが、デバッグするのは非現実的です、読むのはもっともっと簡単です。そして、そのように書く客観的な理由も見当たりません。

 
traveller00:

そして、そのように書く客観的な理由も見当たりません。

もちろん、それらは主観的なものです。不必要な変数やマルチリターンは好きではありません。なぜか、それがないとEX5は短く、実行速度も速くなると思っています。

 
fxsaber:

もちろん、それらは主観的なものです。不必要な変数やマルチリターンは好きではありません。なぜか、EX5はそれらがない方が短く速くなると思っています。

ところで、この「コードが短くなる、速くなる」という自信は、正当なものではありません。

さあて

bool a=A();
bool b=B();
//....много промежуточных результатов
bool x=X();
bool Res=a||b||x ;
return Res;

そして、この

return A()||B()||X();

きっとスピードは同じでしょう(コードや使用メモリのサイズも同じかもしれません)。

ただ、2番目の変種の方が早く書けるのでみんなそれを書き、何かを追加したり複雑にしたりする必要が出てくると、2番目の変種のまま、しかし読みにくいものに肥大化させてしまうのです。

この点については、定期的にリファクタリングを行えば問題ないでしょう。

 
Aleksey Mavrin:

この点については、定期的にリファクタリングを 行えば問題ないでしょう。

自由な時間が多い人、あるいは客観的に見て、これがないとどこにも行けないほど追い詰められている人だけが対象です。

リターンが多いときは、100%コードが違ってきます。
 
fxsaber:

自由な時間が多い人、あるいは客観的に見て、これがないとどこにも 行けないほど追い詰められて いる人だけが対象です。

ZS リターンが多いと、100%コードが違ってきます。

私は理解していますが、一部同意します。ただ、誰もが比較的長いバグフィックス時間を経験しており、コードがデバッグのための「完璧な準備」であれば、より早く発見されるだろうと思います。

使える」コードを長く書くことと、デバッグしてバグを見つけること、どちらが時間を食うかは不明 ですが、いつも違うのでしょう。

 
fxsaber:

リターンが多いときは100%違うコードになる。

デバッガ下のC++ VS2019

のソースコードです。

bool a(int v) { return(v > 0); }
bool b(int v) { return(v < 0); }
bool c(int v) { return(v == 0);}

bool tst1(int v1, int v2, int v3)
{
        if (a(v1)) return(true);
        if (b(v2)) return(true);
        if (c(v3)) return(true);
        return(false);
}

bool tst2(int v1, int v2, int v3)
{
        return(a(v1) && b(v2) && c(v3));
}

int main()
{
        int x = 1, y=2, z=3;
        bool result1 = tst1(x, y, z);
        bool result2 = tst2(x, y, z);
}

アスムデバッガ

bool tst1(int v1, int v2, int v3)
{
        if (a(v1)) return(true);
000 E1918  mov         eax,dword ptr [v1]  
000 E191B  push        eax  
000 E191C  call        a (0 E137Ah)  
000 E1921  add         esp,4  
000 E1924  movzx       ecx,al  
000 E1927  test        ecx,ecx  
000 E1929  je          tst1+3 Fh (0 E192Fh)  
000 E192B  mov         al,1  
000 E192D  jmp         tst1+6 Fh (0 E195Fh)  
        if (b(v2)) return(true);
000 E192F  mov         eax,dword ptr [v2]  
000 E1932  push        eax  
000 E1933  call        b (0 E13ACh)  
000 E1938  add         esp,4  
000 E193B  movzx       ecx,al  
000 E193E  test        ecx,ecx  
000 E1940  je          tst1+56 h (0 E1946h)  
000 E1942  mov         al,1  
000 E1944  jmp         tst1+6 Fh (0 E195Fh)  
        if (c(v3)) return(true);
000 E1946  mov         eax,dword ptr [v3]  
000 E1949  push        eax  
000 E194A  call        c (0 E11B8h)  
000 E194F  add         esp,4  
000 E1952  movzx       ecx,al  
000 E1955  test        ecx,ecx  
000 E1957  je          tst1+6 Dh (0 E195Dh)  
000 E1959  mov         al,1  
000 E195B  jmp         tst1+6 Fh (0 E195Fh)  
        return(false);
000 E195D  xor         al,al  
}


bool tst2(int v1, int v2, int v3)
{
        return(a(v1) && b(v2) && c(v3));
000 E19C8  mov         eax,dword ptr [v1]  
000 E19CB  push        eax  
000 E19CC  call        a (0 E137Ah)  
000 E19D1  add         esp,4  
000 E19D4  movzx       ecx,al  
000 E19D7  test        ecx,ecx  
000 E19D9  je          tst2+6 Dh (0 E1A0Dh)  
000 E19DB  mov         edx,dword ptr [v2]  
000 E19DE  push        edx  
000 E19DF  call        b (0 E13ACh)  
000 E19E4  add         esp,4  
000 E19E7  movzx       eax,al  
000 E19EA  test        eax,eax  
000 E19EC  je          tst2+6 Dh (0 E1A0Dh)  
000 E19EE  mov         ecx,dword ptr [v3]  
000 E19F1  push        ecx  
000 E19F2  call        c (0 E11B8h)  
000 E19F7  add         esp,4  
000 E19FA  movzx       edx,al  
000 E19FD  test        edx,edx  
000 E19FF  je          tst2+6 Dh (0 E1A0Dh)  
000 E1A01  mov         dword ptr [ebp-0 C4h],1  
000 E1A0B  jmp         tst2+77 h (0 E1A17h)  
000 E1A0D  mov         dword ptr [ebp-0 C4h],0  
000 E1A17  mov         al,byte ptr [ebp-0 C4h]  
}



カウントしない2列で1コールだけコマンドで削減。

ts1:                                                    tst2:
000 E1918  mov         eax,dword ptr [v1]                000 E19C8  mov         eax,dword ptr [v1]
000 E191B  push        eax                               000 E19CB  push        eax  
000 E191C  call        a (0 E137Ah)                       000 E19CC  call        a (0 E137Ah)  
000 E1921  add         esp,4                             000 E19D1  add         esp,4  
000 E1924  movzx       ecx,al                            000 E19D4  movzx       ecx,al  
000 E1927  test        ecx,ecx                           000 E19D7  test        ecx,ecx  
000 E1929  je          tst1+3 Fh (0 E192Fh)                000 E19D9  je          tst2+6 Dh (0 E1A0Dh)  
000 E192B  mov         al,1                              000 E19DB  mov         edx,dword ptr [v2]  
000 E192D  jmp         tst1+6 Fh (0 E195Fh)                000 E19DE  push        edx 


このように、コマンドはほとんど同じものを繰り返しているので、最初のテストでは、さらにいくつかのリターンを追加する必要があることは明らかです。

プロセッサの最適化、並列化、そしてマイクロコマンドのレベルで何が起こるかわからないが、99%の信頼性をもって、これらのコードはプロセッサレベルで1クロックまで同じ速度で実行されると思う。