NO. 1 1987年にソロスが書いた 『金融錬金術』では 重要な命題が提唱されています 市場の価格が 未来に対する偏った見方を 示すという意味では 常に間違っていると思います 市場有効性仮説は理論的仮定に過ぎない.実際には,市場参加者は常に合理的ではなく,各時点において,参加者はすべての情報を完全に獲得し,客観的に解釈することはできません.同じ情報であっても,すべてのフィードバックは異なります.
言い換えれば,価格そのものは既に市場参加者の誤った期待を含んでいるので,本質的には市場価格は常に誤っている.これは仲介業者にとって利益の源かもしれません.
NO.2 上記の原則に基づき,非効率的な先物市場では,異なる期間の配達契約の市場影響が常に同期されず,価格設定が完全に有効な理由ではないことも知っています.
次に,同じ取引目標の異なる時点での配達契約の価格に基づいて,両価格の間には大きな差がある場合,異なる期間の先物契約を同時に取引し,時間間仲介を行うことが可能です. コモディティ・フューチャーと同様に,デジタル通貨も時間間仲介契約ポートフォリオが関連している.例えば,OKEX取引所で:ETC週間,ETC来週,ETC四半期.
例えば,ETC週とETC四半期間のスプレッドが長期間5周で維持されていると仮定します.スプレッドが7に達すると,将来のある時点でスプレッドが5に戻ることを期待します.その後,ETC週を売り,ETC四半期を購入してスプレッドをショートすることができます.逆の方です.
NO.3 このスプレッドは存在するが,手動アービタージでは,手動操作の時間がかかり,精度が低いため,価格変動の影響のために多くの不確実性があります.
量的なモデルを通じて 利 arbitrageの機会を把握し 利 arbitrageの取引戦略を開発し プログラムアルゴリズムによって 取引先に自動で取引オーダーを発行し 機会を迅速かつ正確に把握し 効率的に収入を得ることができます これは量的な利 arbitrageの魅力です
この記事では,デジタル通貨取引におけるFMZ定量取引プラットフォームとOKEX取引所のETC先物契約の使い方について説明します.
NO.4 デジタル通貨の時間間仲介戦略を作成する 難易度:普通レベル 戦略的環境 トランザクション目標:Ethereum classic (ETC) スプレッドデータ: ETC週刊 - ETC四半期 取引期間: 5分 位置一致 1:1 トランザクションタイプ:同じ品種 期間間 戦略の論理 ローング・スプレッド・ポジションの購入条件: 経常口座にポジションがない場合,スプレッドがボール・インジケーターのダウントレイルより小さい場合,スプレッド・オーダーをします.これは週にロング・ETCを購入し,四半期にショート・ETCを売ります.
ショートセールス・スプレッドポジション条件: 経常口座にポジションがない場合,スプレッドがボール指標のアップレールより高くなった場合,スプレッドオーダーをします.これは,毎週ショート・ETCを売却し,四半期ごとにロング・ETCを購入します.
長期株価差の購入条件を閉じる: 決済口座が長期ETCの週期ポジションと短期ETCの四半期ポジションを保持し,株価差がBoll指標の中央線よりも高くなった場合,閉じる株価差の注文をします.これは,週にETCを売却し,四半期にETCをカバーするために購入します.
ショートセール・スプレッドポジション条件を閉じる: 経常口座が ETCのショート・週期ポジションと ETCのショート・四半期ポジションを保持し,スプレッドがボール指標のミドルレールより低い場合,スプレッドを閉じるオーダーを設定します.これは: ETCをカバーするために週に買い,四半期に ETCを売却します.
NO.5 上記はデジタル通貨のシンプルな説明です. デジタル通貨の時間間仲介戦略のロジックです. では,自分のアイデアをプログラムにどのように実装しますか? まずFMZの定量取引プラットフォームでフレームワークを構築してみました. 戦略の枠組み
戦略の枠組みは,戦略的思考と取引プロセスに従って簡単に構築できます. 戦略全体は,3つのステップに簡略化できます.
NO.6 次に,実際の取引プロセスと取引の詳細に基づいて,必要な詳細を戦略枠組みに記入する必要があります.
まず 取引前の事前処理 ステップ1: グローバル環境では,必要なグローバル変数を宣言します. チャートを構成するチャートオブジェクトを宣言する バールチャート = { } Chart 関数を呼び出し,チャートを初期化します Var ObjChart = チャート (チャート) 拡散配列を格納する空の配列を宣言する バール= [ ] 履歴データを記録するタイムスタンプ変数を宣言する Var oldTime = 0 について ステップ2: 戦略のための外部パラメータを設定します.
ステップ3:データ処理機能を定義する 基本データ機能:データ ()) コンストラクタを作成するデータとその内部プロパティを定義する.例えば:アカウントデータ,ポジションデータ,K線データタイムスタンプ,アビラージ契約の最新の購入/販売価格 A/B,ポジティブ/リバースアビラージ・スプレッド
位置関数:mp () を取得する 指定された契約と指定された方向のポジションの数を返します. 存在しない場合は false を返します.
K線と指標関数:boll ()) ポジティブ/リバース・アービタージ・スプレッドのデータに基づいて 新しいK線配列を合成し ボール指標で計算された 上/中/下レールのデータを返します
注文機能:取引 () オーダー契約名と取引タイプを入力し,その後,最後の購入/販売価格で注文を配置し,注文を配置した後,結果を返します.注文の2つの異なる方向を同時に注文する必要がありますので,最後の購入/販売価格は,注文契約名に従って関数内で変換されます.
注文をキャンセルする機能: cancelOrders ()) 待機中の注文を一列に並べて,一枚ずつキャンセルします.待機中の注文がある場合は, false を返します.存在しない場合は, true を返します.
プロセス保有単一の契約: isEven ()) アブタージ取引におけるシングルレグの場合は,すべてのポジションを単に閉じて直接処理されます. もちろん,価格を追いかけることもできます.
図を描く機能:図を描く ()) グラフに必要な市場データと指標データを引き出すためにObjChart.add () 方法を呼び出す:アップ,ミドル,ダウンレール,ポジティブ/リバース・アービタージ・スプレッド.
ステップ4: main () の入力関数で,プログラム開始後1回しか実行されないトランザクションの前に,次のコードを実行します.
コンソールにあまり重要でない情報をフィルタリングします SetErrorFilter ()) 取引するデジタル通貨の種類を設定するexchange.IOについて プログラム開始前に描かれたチャートを空く ObjChart.reset ()) プログラムを起動する前に状態バー情報を空にして LogProfitReset ()
NO.7 トランザクション前の上記の事前処理を定義した後,次のステップに移行し,投票モードに入力し,OnTick () 関数を繰り返す必要があります. 投票時に睡眠時間を設定します デジタル通貨取引所の APIには 特定の期間での アクセス制限があります
2つ目は,データを取得して計算する ステップ1: 取引論理のための基礎データオブジェクト,口座残高,boll指標データを取得する.
第3に 注文し 追跡する ステップ1:上記の戦略論理に従って買い物・販売を実行します.まず,価格と指標条件が正しいかどうかを確認し,その後にポジション条件が正しいかどうかを確認し,最後にトレード () オーダー関数を実行します.
ステップ2:注文後,待機中の注文や単一の契約を保持するなどの異常な状況に対処し,チャートを作成する必要があります.
NO.8 上記では,200行以上で簡単なデジタル通貨間の時間間仲介戦略を作成しました. 完全なコードは以下のとおりです:
NO.9 この戦略はトリガーとして機能します リアルマーケットはそれほど単純ではありませんが この例を使って想像力を発揮できます
私の限られた経験に基づいて デジタル通貨市場の現状では 純粋な期間の仲介戦略は リスクのない三角仲介であれ 市場間仲介であれ 実行に値しないということです
理由は,どのデジタル通貨取引所の先物市場であれ,その利回りは法定ではありません. ほぼすべてのデジタル通貨は年初から約70%下落しています. 言い換えれば,戦略は常に通貨を作っていますが,通貨の価格は下落しています.
デジタル通貨市場は既にブロックチェーンを離れています. チューリップのように,価格は常に人々の期待と信頼から来ています.
完全なコードはこちら
// global variable
// Declare a chart object that configures the chart
var chart = {
__isStock: true,
tooltip: {
xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
},
title: {
text: 'Profit and loss chart(detail)'
},
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: 'spread'
},
opposite: false,
},
series: [{
name: "up",
id: "line1,up",
data: []
}, {
name: "middle",
id: "line2,middle",
data: []
}, {
name: "down",
id: "line3,down",
data: []
}, {
name: "basb",
id: "line4,basb",
data: []
}, {
name: "sabb",
id: "line5,sabb",
data: []
}]
};
var ObjChart = Chart(chart); // Drawing object
var bars = []; // Store spread sequence
var oldTime = 0; // Record historical data timestamp
// Parameter
var tradeTypeA = "this_week"; // Arbitrage contract A
var tradeTypeB = "quarter"; // Arbitrage contract B
var dataLength = 10; //Length of indicator cycle
var timeCycle = 1; // The cycle of K-line
var name = "ETC"; // Currency type
var unit = 1; // Quantity of orders
// Basic data
function Data(tradeTypeA, tradeTypeB) { // input arbitrage contract A&B
this.accountData = _C(exchange.GetAccount); // get account data
this.positionData = _C(exchange.GetPosition); // get position data
var recordsData = _C(exchange.GetRecords); //get k-line data
exchange.SetContractType(tradeTypeA); // subscribe arbitrage contract A
var depthDataA = _C(exchange.GetDepth); // deep data of arbitrage contract A
exchange.SetContractType(tradeTypeB); // subscribe arbitrage contract B
var depthDataB = _C(exchange.GetDepth); // deep data of arbitrage contract B
this.time = recordsData[recordsData.length - 1].Time; // get the latest time data
this.askA = depthDataA.Asks[0].Price; // the latest selling price of arbitrage contract A
this.bidA = depthDataA.Bids[0].Price; // the latest buying price of arbitrage contract A
this.askB = depthDataB.Asks[0].Price; // the latest selling price of arbitrage contract B
this.bidB = depthDataB.Bids[0].Price; // the latest buying price of arbitrage contract B
// Positive arbitrage spread(the latest selling price of contract A -the latest buying price of contract B )
this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
// Reverse arbitrage spread(the latest buying price of contract A -the latest selling price of contract B )
this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}
// get position information
Data.prototype.mp = function (tradeType, type) {
var positionData = this.positionData; // get position data
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;
}
// Synthetize new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
var self = {}; // Temporary object
// the median of Positive arbitrage spread and reverse arbitrage spread
self.Close = (this.basb + this.sabb) / 2;
if (this.timeA == this.timeB) {
self.Time = this.time;
} // Comparing two depth data timestamps
if (this.time - oldTime > timeCycle * 60000) {
bars.push(self);
oldTime = this.time;
} // According to the specified time period, insert the spread data object in the K-line array.
if (bars.length > num * 2) {
bars.shift(); // Control K-line array length
} 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], // up rail of boll indicator
middle: boll[1][boll[1].length - 1], // middle rail of boll indicator
down: boll[2][boll[2].length - 1] // down rail of boll indicator
} // Return a processed boll indicator data.
}
// place order
Data.prototype.trade = function (tradeType, type) {
exchange.SetContractType(tradeType); // Resubscribe contract before placing order
var askPrice, bidPrice;
if (tradeType == tradeTypeA) { // if it's contract A
askPrice = this.askA; // set askPrice
bidPrice = this.bidA; // set bidPrice
} else if (tradeType == tradeTypeB) { // if it's contract B
askPrice = this.askB; // set askPrice
bidPrice = this.bidB; // set bidPrice
}
switch (type) { // Match order mode
case "buy":
exchange.SetDirection(type); // Set order mode
return exchange.Buy(askPrice, unit);
case "sell":
exchange.SetDirection(type); // Set order mode
return exchange.Sell(bidPrice, unit);
case "closebuy":
exchange.SetDirection(type); // Set order mode
return exchange.Sell(bidPrice, unit);
case "closesell":
exchange.SetDirection(type); // Set order mode
return exchange.Buy(askPrice, unit);
default:
return false;
}
}
// cancel order
Data.prototype.cancelOrders = function () {
Sleep(500); // delay before canceling, because some exchanges you know...
var orders = _C(exchange.GetOrders); // Get the array of pending orders
if (orders.length > 0) { // if there is pending order
for (var i = 0; i < orders.length; i++) { //check through the array of pending orders
exchange.CancelOrder(orders[i].Id); //cancel pending orders one by one
Sleep(500); //Delay 0.5 seconds
}
return false; // return false if pending orders have been cancelled
}
return true; //return true if there is no pending order
}
// handle holding single contract
Data.prototype.isEven = function () {
var positionData = this.positionData; // get position data
var type = null; // converse position direction
// If the length of the position array divided by some number and the remainder is 2, the result is not equal to 0 or the length of the position array is not equal to 2
if (positionData.length % 2 != 0 || positionData.length != 2) {
for (var i = 0; i < positionData.length; i++) { // check through the array of positions
if (positionData[i].Type == 0) { // if it's long position
type = 10; // Set order parameters
} else if (positionData[i].Type == 1) { // if it's short position
type = -10; // Set order parameters
}
// close all positions
this.trade(positionData[i].ContractType, type, positionData[i].Amount);
}
}
}
// drawing chart
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 condition
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // Create a base 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
// Spread description
// basb = (the latest selling price of contract A - the latest buying price of contract B)
// sabb = (the latest buying price of contract A - the latest selling price of contract B)
if (data.sabb > boll.middle && data.sabb < boll.up) { // if sabb is higher than the middle rail
if (data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
data.trade(tradeTypeA, "closebuy"); // close long position of contract A
}
if (data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
data.trade(tradeTypeB, "closesell"); // close short position of contract B
}
} else if (data.basb < boll.middle && data.basb > boll.down) { // if basb is lower than the middle rail
if (data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
data.trade(tradeTypeA, "closesell"); // close short position of contract A
}
if (data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
data.trade(tradeTypeB, "closebuy"); // close long position of contract B
}
}
if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
if (data.basb < boll.down) { // if basb spread is lower than the down rail
if (!data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
data.trade(tradeTypeA, "buy"); // open long position of contract A
}
if (!data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
data.trade(tradeTypeB, "sell"); // open short position of contract B
}
} else if (data.sabb > boll.up) { // if sabb spread is higher than the up rail
if (!data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
data.trade(tradeTypeA, "sell"); // open short position of contract A
}
if (!data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
data.trade(tradeTypeB, "buy"); // open long position of contract B
}
}
}
data.cancelOrders(); // cancel orders
data.drawingChart(boll); // drawing chart
data.isEven(); // process holding single contract
}
//enter function
function main() {
// filter the information that is not very important in the console
SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
exchange.IO("currency", name + '_USDT'); //Set the cryptocurrency type to be traded
ObjChart.reset(); //Empty the drawn charts before the program starts
LogProfitReset(); //Empty the status bar information before the program starts
while (true) { // Enter polling mode
onTick(); // Execute onTick function
Sleep(500); // sleep for o.5 seconds
}
}
発明者 量化 - 微かな夢良かった!