エキスパート: Arbitrage Synthetic - ページ 3

 
bas:

マキシム・ドミトリエフスキー さん、もし秘密でなければ、このボットのサーバーへのpingは どれくらいでしたか? また、平均実行時間はどれくらいですか? 10msと200msがありますが、アービトラージが存在する間は、これだけでは実行されないことが多いです。

また、リードしているペア以外の残り2つのペアのうち、どちらが「追いつく」かをどうやって判断するのですか?例えば、私は履歴統計を使っていますが、通常EURUSDがリードしている場合、それに追いつくのはクロスではなく、USDの2番目の足です。


残念ながら、このトピックはすでに死んでいる。200ミリ秒というのは、レイテンシー裁定取引にはすでに十分な時間である(400ミリ秒と考えるのは、取引がまだ成立する必要があるため+スリッページ/マークアップ)。

主なアイデアは、合成がすでに変更され、通貨ペアが変更されていない場合は、ほとんどの場合、クォートにディップがあり、それはすぐにそれと同じになるということでした。このボットで短期間取引し、レアルを2、3枚入れたが、1枚は少し儲け、もう1枚は少し損をした。

私は主に最後の半年でこの戦略に多くの質問が生じたという事実のためにボットを置く人々。私の意見を共有する。多くの人がそれについて書いたり、考えたりしているが、自由に感じる例がなかった。現代のブローカーはhftのために設計されていないので、さらなる最適化は無意味であり、一般的に3ポイントの裁定取引は神話であり、1本足または3本足のいずれかの形でそのような裁定取引はありません。

 

一部の通貨(TRY、NZD)では、スキューが何時間も続くことがある)が、事前に知ることはできないし、取引に長く居座るのも面白くない。

シンセティックは2つのペアで構成されている。通常、そのうちの1つだけが「追いつき」、3つ目は立ち止まる。そのため、2つのペアのうちどちらが追いつくかを判断する方法を尋ねたのです。

そして、クロージングはアービトラージが崩壊した後に行われ、そこでは実行 時間はそれほど重要ではない。

なぜ "存在しない "のか? 私は定期的に観察している)しかし、私には十分なスピードがない。

 
bas:

一部の通貨(TRY、NZD)では、スキューが何時間も続くことがある)が、事前に知ることはできないし、取引に長く居座るのも面白くない。

シンセティックは2つのペアで構成されている。通常、そのうちの1つだけが「追いつき」、3つ目は立ち止まる。そのため、2つのペアのうちどちらが追いつくかを判断する方法を尋ねたのです。

そして、クロージングはアービトラージが崩壊した後に行われ、そこでは実行 時間はそれほど重要ではない。

なぜ "存在しない "のですか? 私は定期的に見ています)しかし、私には十分なスピードがありません。


スピードがないから存在しない。

そして、それはしばしば見積もりの遅延のために発生し、あなたは遅延しているか、まったく現実でない指示見積もりを取得します。

あなたが言っているような歪みは、証券会社が気づいたときに後で修正されるのです。

だから、どちらが追いつくかを判断する方法を尋ねたのです。

基本的には無理で、実験的にやるか、3本足でトレードするしかない。少なくとも、遅れをとっているのが我々のペアである確率は33%で、これは決して小さい数字ではない)

 
オーケー、存在しないから、存在しないんだ)
 
bas:
わかった、存在しないんだ、だから存在しないんだ)

いや、でも、あなたが望むなら、私は最後の例では真実ではないんだ :))

私は自分の経験ですべてをチェックする...そして他の人の経験でも。時間が惜しいなら、しない方がいい。

イエラーシュのように "ここには魚はいない!"(何度も)。

- 誰が言ったんだ?

- 誰って、スタジアムの監督だよ!

 
Maxim Dmitrievsky:

いや......まあ、それでもよかったら試してみてくれ。)

僕は自分の経験と他の人の経験ですべてをチェックするんだ。時間が惜しいなら、やらない方がいい。

イエラーシュのように、"ここには魚はいない!"(何度も)。

- 誰が言ったんだ?

- 誰って、スタジアムの監督だよ!


- スケートリンクの監督だ。

 

つまり、ティックをスキップするOnTimerをOnChartEventに 置き換えるのです。OnChartEventは すべてのインストゥルメントからティックを受信します。インジケータはここから - https://www.mql5.com/en/articles/234

一般的には、はい、魚はいません、ピプシングは小売向けではありません、スプレッド+手数料を考慮すると、メインの三角形では、わずかな利益で年間3回しか取引できません、そして、理想的な世界ではEURUSD / GBPUSD = EURGBPなので、そのブローカーはそれを与えないかもしれません、そして、その逆が起こった場合、それは非市場引用です:)

#include <AIV/Trades.mqh>
#include <AIV/Charts.mqh>

input int InpMagic = 0;
input double InpFactor = 2;
input double InpVolume = 0.01;
input double InpCommission = 30;
input string iACName = "EURUSD";
input string iBCName = "GBPUSD";
input string iABName = "EURGBP";

int iDirection;

SSymbol iACData = {0};
SSymbol iBCData = {0};
SSymbol iABData = {0};

SSeries iSeries[];

CSets * iSets;
CHelpers * iHelpers;
CPositions * iPositions;

void OnDeinit(const int reason)
{
    delete(iSets);
    delete(iHelpers);
    delete(iPositions);
}

int OnInit()
{
    long chart = ChartID();

    iSets = new CSets();
    iHelpers = new CHelpers();
    iPositions = new CPositions();

    iCustom(iACName, PERIOD_M1, "AIV\\Spy", chart, 1);
    iCustom(iBCName, PERIOD_M1, "AIV\\Spy", chart, 2);
    iCustom(iABName, PERIOD_M1, "AIV\\Spy", chart, 3);

    return 0;
}

void Trade()
{
    int positions = PositionsTotal();

    double incomeAC = iPositions.getPositionsIncome(iACName, 0, InpMagic);
    double incomeBC = iPositions.getPositionsIncome(iBCName, 0, InpMagic);
    double incomeAB = iPositions.getPositionsIncome(iABName, 0, InpMagic);

    // 商品のボラティリティを揃える

    double sizeAC = InpVolume / iHelpers.getTickCost(iACName);
    double sizeBC = InpVolume / iHelpers.getTickCost(iBCName);
    double sizeAB = InpVolume / iHelpers.getTickCost(iABName);

    // トライアングルで利益が出たら、ポジションをクローズする。

    if (positions > 0)
    {
        if (incomeAC + incomeBC + incomeAB > 0) 
        {
            iPositions.closePositions(NULL, 0, InpMagic);
            return;
        }
    }
    else
    {
        int direction = isGap();

        // 合成がEURGBPより上にある場合

        if (direction == 1) 
        {
            iDirection = direction;
            iPositions.openSimplePosition(iACName, iDirection * -1, sizeAC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iBCName, iDirection, sizeBC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iABName, iDirection, sizeAB, 0, 0, 0, InpMagic);
        }
        else if (direction == -1) // EURGBP が高いとき
        {
            iDirection = direction;
            iPositions.openSimplePosition(iACName, iDirection, sizeAC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iBCName, iDirection * -1, sizeBC, 0, 0, 0, InpMagic);
            iPositions.openSimplePosition(iABName, iDirection * -1, sizeAB, 0, 0, 0, InpMagic);
        }
    }
}

int isGap()
{
    if (iACData.mUnit <= 0 || iBCData.mUnit <= 0 || iABData.mUnit <= 0)
    {
        return 0;
    }

    double X = iACData.mUnit / iBCData.mUnit;
    double Y = iABData.mUnit;
    double spread = 2 * (iACData.mMean + iBCData.mMean + iABData.mMean);

    double commission = 
        2 * iACData.mUnit * iHelpers.moneyToPips(iACName, InpVolume, InpCommission * InpVolume) + 
        2 * iBCData.mUnit * iHelpers.moneyToPips(iBCName, InpVolume, InpCommission * InpVolume) + 
        2 * iABData.mUnit * iHelpers.moneyToPips(iABName, InpVolume, InpCommission * InpVolume);

    // 距離 EURUSD / GBPUSD - EURGBP > コミッション + スプレッド

    if (X - Y - spread - commission > 0)
    {
        return 1;
    }
    else if (Y - X - spread - commission > 0) // その逆もある。
    {
        return -1;
    }

    return 0;
}

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
    if (id > CHARTEVENT_CUSTOM) 
    {
        string message[];

        // Aggregate prices from 3 charts here, every "sparam" contains data in format "EURUSD:1.22350:30" or "GBPUSD:1.52450:15" or "EURGBP:1.22350:3"

        StringSplit(sparam, ':', message);

        if (ArraySize(message) < 3)
        {
            return;
        }

        string symbol = message[0];
        int event = id - CHARTEVENT_CUSTOM;
        double close = StringToDouble(message[1]);
        double spread = StringToDouble(message[2]) * SymbolInfoDouble(symbol, SYMBOL_POINT);

        if (symbol == iACName)
        {
            iACData.mName = symbol;
            iACData.mUnit = close;
            iACData.mMean = spread;
        }
        else if (symbol == iBCName)
        {
            iBCData.mName = symbol;
            iBCData.mUnit = close;
            iBCData.mMean = spread;
        }
        else if (symbol == iABName)
        {
            iABData.mName = symbol;
            iABData.mUnit = close;
            iABData.mMean = spread;
        }
 
        // 3つのペアの価格が揃ったときのみ取引する。

        if (iACData.mUnit > 0 && iBCData.mUnit > 0 && iABData.mUnit > 0)
        {
            Trade();
        }
    }
}

念のため、Spyインジケータのコードを簡略化しておきます :)

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1

input long InpChart = 0;
input ushort InpEventId = 0;

int OnCalculate (
    const int bars,
    const int counted,
    const datetime& times[],
    const double& opens[],
    const double& highs[],
    const double& lows[],
    const double& closes[],
    const long& ticks[],
    const long& volumes[],
    const int& spreads[])
{
    string close = DoubleToString(closes[bars - 1]);
    string spread = DoubleToString(spreads[bars - 1]);
    EventChartCustom(InpChart, InpEventId, (long) Period(), bars, Symbol() + ":" + close + ":" + spread); // すべてのチャートのティックを単一のイベント・ハンドラに変換する。
    return bars;
}
 
Andy Sanders:

念のため、Spyインジケータのコードを簡略化しました。)

代替バリアント

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

このようにすることもできますが、私の場合、各シンボルに対して別々の SymbolInfoTick 呼び出しで EA コードをごちゃごちゃにしないように、sparam を通して「EURUSD:1.22350:30」というデータの束を渡しています。

 

また、興味のある方は、スワップ口座用ではなく、実際の株式
https://www.quantconnect.com/forum/discussion/1257/pairs-trading-with-coke--pepsi、リバランシングとホールドによるペア・トレーディングの興味深い実装があります。