資源の読み込みに... 荷物...

デジタル通貨のクロスペリオド仲裁戦略 ボリンジャー帯に基づく

作者: リン・ハーンFMZ~リディア, 作成日:2022-12-02 16:58:27, 更新日:2023-09-20 09:33:29

img

デジタル通貨のクロスペリオド仲裁戦略 ボリンジャー帯に基づく

I.要約

ジョージ・ソロスは,1987年に書いた"The Alchemy of Finance"で重要な命題を提出した.私は市場価格が常に誤っていると信じている.それは,将来に対する偏見を示しているという意味です.市場効率の仮説は単なる理論的仮説です.実際には,市場参加者は常に合理的ではなく,各時点において,参加者はすべての情報を完全に入手し,客観的に解釈することはできません.さらに,同じ情報であっても,すべてのフィードバックは異なります.つまり,価格自体にはすでに市場参加者の間違った期待が含まれています.したがって,本質的には,市場価格は常に間違っている.これは仲介者の利益源かもしれません.

戦略的原則

上記の原則によると,非効率な先物市場では,異なる期間の配送契約に対する市場の影響が常に同期ではなく,価格設定が完全に効果的でない理由がわかる.次に,異なる期間の同じ取引対象の配送契約価格に基づいて,両価格の価格差が大きい場合,クロス期間の仲介のために異なる期間の先物契約を同時に購入・販売することができます.商品先物と同様に,デジタル通貨もクロス期間の仲介契約ポートフォリオを持っています.例えば,OKEX取引所で,以下があります: ETC 現週,ETC 来週,ETC 四半期. 例えば,当週のETCとETCの四半期間の価格差が長期間約5にとどまると仮定します.価格差が1日7に達すると,将来的には価格差が5に戻ると予想します.その後,当週ETCを売却し,同時期にETC四半期を購入して価格差をショートすることができます.その反対に.この価格差が存在しているにもかかわらず,手動手動操作,精度低下,価格変動の影響により手動仲介には多くの不確実性があります.定量仲介の魅力は,定量モデルや仲介取引戦略の策定を通じて仲介機会を把握し,また,プログラムされたアルゴリズムを通じて取引所に自動的に取引オーダーを置き,機会を迅速かつ正確に把握し,効率的かつ安定的に利益を得ることにあります.

戦略の論理

この記事では,FMZ量子取引プラットフォームとOKEX取引所のETC先物契約の使い方を教え,即時の仲介機会を把握し,毎回見られる利益を把握し,簡単な仲介戦略でデジタル通貨取引で遭遇するリスクをヘッジする方法を示します.

デジタル通貨のクロス・ペリオド・アービタージ戦略を作成する

難しさ: 普通

戦略環境

  • 取引対象:Ether Classic (ETC)
  • スプレッドデータ: ETCの現在の週 - ETCの四半期 (共同統合テストを省略)
  • 取引期間: 5分
  • 位置一致:1:1
  • トランザクションタイプ:同じタイプのクロス期

戦略の論理

  • 価格差を長期化してポジションを開設する条件:当日口座にポジションがない場合,価格差がボールの下限未満である場合は,価格差を長期化します.つまり,週間の開設ポジション ETCを購入し,四半期の開設ポジション ETCを販売します.
  • 価格差をショートしてポジションを開設する条件:当日口座にポジションがない場合,価格差がボールの上限よりも大きい場合は,価格差をショートします.つまり,週間の開設ポジション ETCを販売し,四半期の開設ポジション ETCを購入します.
  • 価格差を長引いてポジションを閉じる条件:当日週に ETCの長引いたオーダーを保有し,四半期に ETCの短引いたオーダーを保有し,価格差がボールの中間線よりも大きい場合,価格差を長引いて閉じる.つまり,週間のETCの閉店ポジションを売却し,四半期のETCの閉店ポジションを購入する.
  • 価格差をショートしてポジションを閉じる条件:当日週に現在の口座がETCのショートオーダーを継続し,ETC四半期のショートオーダーを継続し,価格差がボールの中間境界よりも小さい場合,価格差をショートして閉じる.つまり,週間のETCの閉店ポジションを購入し,四半期のETCの閉店ポジションを売る.

IV 戦略の枠組みを書き出す

上記はデジタル通貨のクロス・ペリオド・アビトラージ戦略の単純な論理説明です. では,このプログラムで私たちのアイデアをどのように実装しますか? FMZ量子取引プラットフォームのフレームワークを構築しようとしています.

function Data() {}  // Basic data function
Data.prototype.mp = function () {}  // Position function
Data.prototype.boll = function () {}  // Indicator function
Data.prototype.trade = function () {}  // Order placement function
Data.prototype.cancelOrders = function () {}  // Order withdrawal function
Data.prototype.isEven = function () {}  // Processing single contract function
Data.prototype.drawingChart = function () {}  // Drawing function

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB);  // Create a basic data object
    var accountStocks = data.accountData.Stocks;  // Account balance
    var boll = data.boll(dataLength, timeCycle);  // Calculate the technical indicators of boll
    data.trade();  // Calculate trading conditions to place an order
    data.cancelOrders();  // Cancel orders
    data.drawingChart(boll);  // drawing
    data.isEven();  // Processing of holding individual contract
}

//Entry function
function main() {
    while (true) {  // Enter the polling mode
        onTick();  // Execute onTick function
        Sleep(500);  // Sleep for 0.5 seconds
    }
}

V. 策略の書き込み

戦略の枠組みは,戦略のアイデアとトランザクションプロセスに従って簡単に設定できます. 戦略全体が3つのステップに簡素化できます. 取引前の事前処理 データを集めて計算します 注文して後で処理する 次に,実際の取引プロセスと取引の詳細に従って,必要な詳細コードを戦略枠に記入する必要があります.

取引前の事前処理 ステップ1: 必要なグローバル変数をグローバル範囲で宣言する.

//Declare a chart object for the configuration chart
var chart = { }

//Call Chart function and initialize the chart
var ObjChart = Chart ( chart )

//Declare an empty array to store price difference series
var bars = [ ]

//Declare a record history data timestamp variable
var oldTime = 0

ステップ2: 戦略の外部パラメータを設定する

// parameters
var tradeTypeA = "this_week"; // Arbitrage A Contract
var tradeTypeB = "quarter"; // Arbitrage B Contract
var dataLength = 10; //Indicator period length
var timeCycle = 1; // K-line period
var name = "ETC"; // Currencies
var unit = 1; // Order quantity

ステップ3:データ処理機能を定義する 基本データ機能:データ (※) コンストラクタ,データを作成し,その内部プロパティを定義します.アカウントデータ,ポジションデータ,K線データタイムスタンプ,アビタージA/B契約の購入/販売価格,およびポジティブ/ネガティブなアビタージ価格差を含む.

// Basic data
function Data(tradeTypeA, tradeTypeB) { // Pass in arbitrage A contract and arbitrage B contract
    this.accountData = _C(exchange.GetAccount); // Get account information
    this.positionData = _C(exchange.GetPosition); // Get position information
    var recordsData = _C(exchange.GetRecords); // Get K-line data
    exchange.SetContractType(tradeTypeA); // Subscription arbitrage A contract
    var depthDataA = _C(exchange.GetDepth); // Depth data of arbitrage A contract
    exchange.SetContractType(tradeTypeB); // Subscription arbitrage B contract
    var depthDataB = _C(exchange.GetDepth); // Depth data of arbitrage B contract
    this.time = recordsData[recordsData.length - 1].Time; // Time of obtaining the latest data
    this.askA = depthDataA.Asks[0].Price; // Sell one price of Arbitrage A contract
    this.bidA = depthDataA.Bids[0].Price; // Buy one price of Arbitrage A contract
    this.askB = depthDataB.Asks[0].Price; // Sell one price of Arbitrage B contract
    this.bidB = depthDataB.Bids[0].Price; // Buy one price of Arbitrage B contract
    // Positive arbitrage price differences (Sell one price of contract A - Buy one price of contract B)
    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
    // Negative arbitrage price differences (Buy one price of contract A - Sell one price of contract B)
    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}

位置関数:mp () を取得する 指定された契約と方向の位置量返します. そうでなければ,返します false

// Get positions
Data.prototype.mp = function (tradeType, type) {
    var positionData = this.positionData; // Get position information
    for (var i = 0; i < positionData.length; i++) {
        if (positionData[i].ContractType == tradeType) {
            if (positionData[i].Type == type) {
                if (positionData[i].Amount > 0) {
                    return positionData[i].Amount;
                }
            }
        }
    }
    return false;
}

K線とインジケータ機能:boll ((() 新しいK線配列は,ポジティブ・アビラージ/ネガティブ・アビラージ価格差データに基づいて合成される.ボール指標で計算された上位トラック,中位トラック,下位トラックデータは返される.

// Synthesis of new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
    var self = {}; // Temporary objects
    // Median value of positive arbitrage price difference and negative arbitrage price difference
    self.Close = (this.basb + this.sabb) / 2;
    if (this.timeA == this.timeB) {
        self.Time = this.time;
    } // Compare two depth data timestamps
    if (this.time - oldTime > timeCycle * 60000) {
        bars.push(self);
        oldTime = this.time;
    } // Pass in the price difference data object into the K-line array according to the specified time period
    if (bars.length > num * 2) {
        bars.shift(); // Control the length of the K-line array
    } else {
        return;
    }
    var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the talib library
    return {
        up: boll[0][boll[0].length - 1], // boll indicator upper track
        middle: boll[1][boll[1].length - 1], // boll indicator middle track
        down: boll[2][boll[2].length - 1] // boll indicator down track
    } // Return a processed boll indicator data
}

オーダー機能:取引 オーダー契約名とオーダータイプを入力し,その後,対価でオーダーを配置し,オーダーを配置した後,結果を返します.同時に異なる方向に2つのオーダーを配置することが必要であるため,購入/販売の1つの価格は,オーダーの契約名に従って関数内で変換されます.

// place the order
Data.prototype.trade = function (tradeType, type) {
    exchange.SetContractType(tradeType); // Resubscribe to a contract before placing an order
    var askPrice, bidPrice;
    if (tradeType == tradeTypeA) { // If the order is placed in contract A
        askPrice = this.askA; // set askPrice
        bidPrice = this.bidA; // set bidPrice
    } else if (tradeType == tradeTypeB) { // If the order is placed in contract B
        askPrice = this.askB; // set askPrice
        bidPrice = this.bidB; // set bidPrice
    }
    switch (type) { // Match order placement mode
        case "buy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        case "sell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closebuy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closesell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        default:
            return false;
    }
}

注文をキャンセルする機能: cancelOrders ((() 注文が完了していない場合は false が返され,完了していない場合は true が返されます.

// Cancel order
Data.prototype.cancelOrders = function () {
    Sleep(500); // Delay before cancellation, because some exchanges, you know what I mean
    var orders = _C(exchange.GetOrders); // Get an array of unfilled orders
    if (orders.length > 0) { // If there are unfilled orders
        for (var i = 0; i < orders.length; i++) { //Iterate through the array of unfilled orders
            exchange.CancelOrder(orders[i].Id); //Cancel unfilled orders one by one
            Sleep(500); //Delay 0.5 seconds
        }
        return false; // Return false if an unfilled order is cancelled
    }
    return true; // Return true if there are no unfilled orders
}

単一の契約を保持するハンドル: isEven ((() アブタージ取引の単一のステップの場合,我々は単にすべてのポジションを閉鎖します. もちろん,それは追跡方法にも変更することができます.

// Handle holding a single contract
Data.prototype.isEven = function () {
    var positionData = this.positionData; // Get position information
    var type = null; // Switch position direction
    // If the remaining 2 of the position array length is not equal to 0 or the position array length is not equal to 2
    if (positionData.length % 2 != 0 || positionData.length != 2) {
        for (var i = 0; i < positionData.length; i++) { // Iterate through the position array
            if (positionData[i].Type == 0) { // If it is a long order
                type = 10; // Set order parameters
            } else if (positionData[i].Type == 1) { // If it is a short order
                type = -10; // Set order parameters
            }
            // Close all positions
            this.trade(positionData[i].ContractType, type, positionData[i].Amount);
        }
    }
}

図面 () ObjChart Add () メソッドを呼び出し,必要な市場データと指標データをチャートに描く:上線,中線,下線,正/負のアビラージ価格差.

// Drawing
Data.prototype.drawingChart = function (boll) {
    var nowTime = new Date().getTime();
    ObjChart.add([0, [nowTime, boll.up]]);
    ObjChart.add([1, [nowTime, boll.middle]]);
    ObjChart.add([2, [nowTime, boll.down]]);
    ObjChart.add([3, [nowTime, this.basb]]);
    ObjChart.add([4, [nowTime, this.sabb]]);
    ObjChart.update(chart);
}

ステップ4: main () の入力関数で,プログラム開始後1回しか実行されない,トランザクション前の処理前のコードを実行します.

  • SetErrorFilter (()) は,コンソール内の非重要な情報をフィルタリングする
  • exchange.IO ( https://www.squadhelp.com/name/exchange.io?lp=d取引されるデジタル通貨を設定する
  • ObjChartリセット ( ) プログラム開始前に描かれた前のチャートをクリアする
  • LogProfitReset (ログプロフィットリセット) は,プログラムを起動する前に状態バー情報を削除します.
//entry function
function main() {
    // Filter the unimportant information in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the digital currency to be traded
    ObjChart.reset(); // Clear the previous chart drawn before starting the program
    LogProfitReset(); // Clear the status bar information before starting the program
}

上記のトランザクション前の事前処理が定義された後,次のステップは,投票モードに入り,オンティック (onTick)) 関数を繰り返し実行することです.一部のデジタル通貨取引所のAPIには,特定の時間帯のアクセス制限が組み込まれているため,Sleep () 投票の睡眠時間を設定します.

//entry function
function main() {
    // Filter the unimportant information in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the digital currency to be traded
    ObjChart.reset(); //Clear the previous chart drawn before starting the program
    LogProfitReset(); //Clear the status bar information before starting the program
    while (true) { // Enter the polling mode
        onTick(); // Execute onTick function
        Sleep(500); // Sleep for 0.5 seconds
    }
}

データを取得して計算する ステップ1: 取引論理で使用するための基本データオブジェクト,口座残高,およびボール指標データを取得する.

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
}

注文して後継を処理します ステップ1:上記の戦略的論理に従って購入販売操作を実行します.まず,価格と指標条件が有効かどうかを判断し,その後,ポジション条件が有効かどうかを判断し,最後に取引 () オーダー関数を実行します.

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
    // Explanation of the price difference
    // basb = (Sell one price of contract A - Buy one price of contract B)
    // sabb = (Buy one price of contract A - Sell one price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // If sabb is higher than the middle track
        if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
            data.trade(tradeTypeA, "closebuy"); // Contract A closes long position
        }
        if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
            data.trade(tradeTypeB, "closesell"); // Contract B closes short position
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // If basb is lower than the middle track
        if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
            data.trade(tradeTypeA, "closesell"); // Contract A closes short position
        }
        if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
            data.trade(tradeTypeB, "closebuy"); // Contract B closes long position
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
        if (data.basb < boll.down) { // If basb price difference is lower than the down track
            if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
                data.trade(tradeTypeA, "buy"); // Contract A opens long position
            }
            if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
                data.trade(tradeTypeB, "sell"); // Contract B opens short position
            }
        } else if (data.sabb > boll.up) { // If sabb price difference is higher than the upper track
            if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
                data.trade(tradeTypeA, "sell"); // Contract A opens short position
            }
            if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
                data.trade(tradeTypeB, "buy"); // Contract B opens long position
            }
        }
    }
}

ステップ2:オーダーが発注された後,未定のオーダーや単一の契約の保持などの異常な状況に対処する必要があります. そしてチャートを描きます.

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
    // Explanation of the price difference
    //basb = (Sell one price of contract A - Buy one price of contract B)
    // sabb = (Buy one price of contract A - Sell one price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // If sabb is higher than the middle track
        if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
            data.trade(tradeTypeA, "closebuy"); // Contract A closes long position
        }
        if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
            data.trade(tradeTypeB, "closesell"); // Contract B closes short position
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // If basb is lower than the middle track
        if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
            data.trade(tradeTypeA, "closesell"); // Contract A closes short position
        }
        if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
            data.trade(tradeTypeB, "closebuy"); // Contract B closes long position
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
        if (data.basb < boll.down) { // If basb price difference is lower than the down track
            if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
                data.trade(tradeTypeA, "buy"); // Contract A opens long position
            }
            if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
                data.trade(tradeTypeB, "sell"); // Contract B opens short position
            }
        } else if (data.sabb > boll.up) { // If sabb price difference is higher than the upper track
            if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
                data.trade(tradeTypeA, "sell"); // Contract A opens short position
            }
            if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
                data.trade(tradeTypeB, "buy"); // Contract B opens long position
            }
        }
    }
    data.cancelOrders(); // cancel orders
    data.drawingChart(boll); // drawing
    data.isEven(); // Handle holding individual contracts
}

VI. 総合戦略

デジタル通貨の簡単なクロス・ペリオド・アービタージ戦略を 200行以上のコードで作成しました. 完全なコードは以下のとおりです:

// Global variable
// Declare a chart object for the configuration chart
var chart = {
    __isStock: true,
    tooltip: {
        xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
    },
    title: {
        text: 'transaction profit and loss curve (detailed)'
    },
    rangeSelector: {
        buttons: [{
            type: 'hour',
            count: 1,
            text: '1h'
        }, {
            type: 'hour',
            count: 2,
            text: '3h'
        }, {
            type: 'hour',
            count: 8,
            text: '8h'
        }, {
            type: 'all',
            text: 'All'
        }],
        selected: 0,
        inputEnabled: false
    },
    xAxis: {
        type: 'datetime'
    },
    yAxis: {
        title: {
            text: 'price difference'
        },
        opposite: false,
    },
    series: [{
        name: "upper track",
        id: "line1,up",
        data: []
    }, {
        name: "middle track",
        id: "line2,middle",
        data: []
    }, {
        name: "down track",
        id: "line3,down",
        data: []
    }, {
        name: "basb",
        id: "line4,basb",
        data: []
    }, {
        name: "sabb",
        id: "line5,sabb",
        data: []
    }]
};
var ObjChart = Chart(chart); // Drawing object
var bars = []; // Storage price difference series
var oldTime = 0; // Record historical data timestamp

// parameters
var tradeTypeA = "this_week"; // Arbitrage A contract
var tradeTypeB = "quarter"; // Arbitrage B contract
var dataLength = 10; //Indicator period length
var timeCycle = 1; // K-line period
var name = "ETC"; // Currencies
var unit = 1; // Order quantity

// basic data
function Data(tradeTypeA, tradeTypeB) { // Pass in arbitrage A contract and arbitrage B contract
    this.accountData = _C(exchange.GetAccount); // Get account information
    this.positionData = _C(exchange.GetPosition); // Get position information
    var recordsData = _C(exchange.GetRecords); //Get K-line data
    exchange.SetContractType(tradeTypeA); // Subscribe to arbitrage A contract
    var depthDataA = _C(exchange.GetDepth); // Arbitrage A contract depth data
    exchange.SetContractType(tradeTypeB); // Subscribe to arbitrage B contract
    var depthDataB = _C(exchange.GetDepth); // Arbitrage B contract depth data
    this.time = recordsData[recordsData.length - 1].Time; // Time to get the latest data
    this.askA = depthDataA.Asks[0].Price; // Sell one price of arbitrage A contract
    this.bidA = depthDataA.Bids[0].Price; // Buy one price of arbitrage A contract
    this.askB = depthDataB.Asks[0].Price; // Sell one price of arbitrage B contract
    this.bidB = depthDataB.Bids[0].Price; // Buy one price of arbitrage B contract
    // Positive arbitrage price difference (Sell one price of contract A - Buy one price of contract B)
    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
    // Negative arbitrage price difference (Buy one price of contract A - Sell one price of contract B)
    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}

// Get position
Data.prototype.mp = function (tradeType, type) {
    var positionData = this.positionData; // Get position information
    for (var i = 0; i < positionData.length; i++) {
        if (positionData[i].ContractType == tradeType) {
            if (positionData[i].Type == type) {
                if (positionData[i].Amount > 0) {
                    return positionData[i].Amount;
                }
            }
        }
    }
    return false;
}

// Synthesis of new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
    var self = {}; // Temporary objects
    // Median value of between positive arbitrage price difference and negative arbitrage price difference
    self.Close = (this.basb + this.sabb) / 2;
    if (this.timeA == this.timeB) {
        self.Time = this.time;
    } // Compare two depth data timestamps
    if (this.time - oldTime > timeCycle * 60000) {
        bars.push(self);
        oldTime = this.time;
    } // Pass in the price difference data object into the K-line array according to the specified time period
    if (bars.length > num * 2) {
        bars.shift(); // Control the length of the K-line array
    } else {
        return;
    }
    var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the talib library
    return {
        up: boll[0][boll[0].length - 1], // boll indicator upper track
        middle: boll[1][boll[1].length - 1], // boll indicator middle track
        down: boll[2][boll[2].length - 1] // boll indicator down track
    } // Return a processed boll indicator data
}

// Place an order
Data.prototype.trade = function (tradeType, type) {
    exchange.SetContractType(tradeType); // Resubscribe to a contract before placing an order
    var askPrice, bidPrice;
    if (tradeType == tradeTypeA) { // If the order is placed in contract A
        askPrice = this.askA; // Set askPrice
        bidPrice = this.bidA; // Set bidPrice
    } else if (tradeType == tradeTypeB) { // If the order is placed in contract B
        askPrice = this.askB; // Set askPrice
        bidPrice = this.bidB; // Set bidPrice
    }
    switch (type) { // Match order placement mode
        case "buy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        case "sell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closebuy":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Sell(bidPrice, unit);
        case "closesell":
            exchange.SetDirection(type); // Set order placement mode
            return exchange.Buy(askPrice, unit);
        default:
            return false;
    }
}

// Cancel orders
Data.prototype.cancelOrders = function () {
    Sleep(500); // Delay before cancellation, because some exchanges, you know what I mean
    var orders = _C(exchange.GetOrders); //Get an array of unfilled orders
    if (orders.length > 0) { // If there are unfilled orders
        for (var i = 0; i < orders.length; i++) { //Iterate through the array of unfilled orders
            exchange.CancelOrder(orders[i].Id); //Cancel unfilled orders one by one
            Sleep(500); //Sleep for 0.5 seconds
        }
        return false; // Return false if an unfilled order is cancelled
    }
    return true; //Return true if there are no unfilled orders
}

// Handle holding individual contracts
Data.prototype.isEven = function () {
    var positionData = this.positionData; // Get position information
    var type = null; // Switch position direction
    // If the remaining 2 of the position array length is not equal to 0 or the position array length is not equal to 2
    if (positionData.length % 2 != 0 || positionData.length != 2) {
        for (var i = 0; i < positionData.length; i++) { // Iterate through the position array
            if (positionData[i].Type == 0) { // If it is a long order
                type = 10; // Set order parameters
            } else if (positionData[i].Type == 1) { // If it is a short order
                type = -10; // Set order parameters
            }
            // Close all positions
            this.trade(positionData[i].ContractType, type, positionData[i].Amount);
        }
    }
}

// Drawing
Data.prototype.drawingChart = function (boll) {
    var nowTime = new Date().getTime();
    ObjChart.add([0, [nowTime, boll.up]]);
    ObjChart.add([1, [nowTime, boll.middle]]);
    ObjChart.add([2, [nowTime, boll.down]]);
    ObjChart.add([3, [nowTime, this.basb]]);
    ObjChart.add([4, [nowTime, this.sabb]]);
    ObjChart.update(chart);
}

// Trading conditions
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a basic data object
    var accountStocks = data.accountData.Stocks; // Account balance
    var boll = data.boll(dataLength, timeCycle); // Get boll indicator data
    if (!boll) return; // Return if there is no boll data
    // Explanation of price difference
    // basb = (Sell one price of contract A - Buy one price of contract B)
    // sabb = (Buy one price of contract A - Sell one price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // If sabb is higher than the middle track
        if (data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
            data.trade(tradeTypeA, "closebuy"); // Contract A closes long position
        }
        if (data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
            data.trade(tradeTypeB, "closesell"); // Contract B closes short position
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // If basb is lower than the middle track
        if (data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
            data.trade(tradeTypeA, "closesell"); // Contract A closes short position
        }
        if (data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
            data.trade(tradeTypeB, "closebuy"); // Contract B closes long position
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is a balance in the account
        if (data.basb < boll.down) { // If basb price difference is lower than the down track
            if (!data.mp(tradeTypeA, 0)) { // Check whether contract A has long orders before placing an order
                data.trade(tradeTypeA, "buy"); // Contract A opens long position
            }
            if (!data.mp(tradeTypeB, 1)) { // Check whether contract B has short orders before placing an order
                data.trade(tradeTypeB, "sell"); // Contract B opens short position
            }
        } else if (data.sabb > boll.up) { // If sabb price difference is higher than the upper track
            if (!data.mp(tradeTypeA, 1)) { // Check whether contract A has short orders before placing an order
                data.trade(tradeTypeA, "sell"); // Contract A opens short position
            }
            if (!data.mp(tradeTypeB, 0)) { // Check whether contract B has long orders before placing an order
                data.trade(tradeTypeB, "buy"); // Contract B opens long position
            }
        }
    }
    data.cancelOrders(); // Cancel orders
    data.drawingChart(boll); // Drawing
    data.isEven(); // Handle holding individual contracts
}

//Entry function
function main() {
    // Filter unimportant information in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the digital currency to be traded
    ObjChart.reset(); //Clear the previous chart drawn before starting the program
    LogProfitReset(); //Clear the status bar information before starting the program
    while (true) { // Enter polling mode
        onTick(); // Execute the onTick function
        Sleep(500); // Sleep for 0.5 seconds
    }
}

戦略アドレス:https://www.fmz.com/strategy/104964

VII.要約

この記事の戦略は単なる例です. 本物のボットは簡単ではありませんが,その例をたどり,自分の野蛮な想像力を使用することができます. 私の限られた経験に基づいて,現在のデジタル通貨市場で,ほとんどすべての純粋な先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物 理由は,どのデジタル通貨交換先物市場であろうと,その利回りは法定通貨ではない. 現時点では,ほぼすべてのデジタル通貨は年初から約70%減少しています. つまり,戦略は常に通貨を稼ぐことですが,通貨価格は減少しています. 全体として,デジタル通貨市場はブロックチェーンから切り離されたようです. 当時,チューリップのように,価格は常に人々の期待と信頼から来ています. そして信頼は価格から来ています...


関連性

もっと