ジョージ・ソロスは,1987年に書いた"The Alchemy of Finance"で重要な命題を提出した.私は市場価格が常に誤っていると信じている.それは,将来に対する偏見を示しているという意味です.市場効率の仮説は単なる理論的仮説です.実際には,市場参加者は常に合理的ではなく,各時点において,参加者はすべての情報を完全に入手し,客観的に解釈することはできません.さらに,同じ情報であっても,すべてのフィードバックは異なります.つまり,価格自体にはすでに市場参加者の間違った期待が含まれています.したがって,本質的には,市場価格は常に間違っている.これは仲介者の利益源かもしれません.
上記の原則によると,非効率な先物市場では,異なる期間の配送契約に対する市場の影響が常に同期ではなく,価格設定が完全に効果的でない理由がわかる.次に,異なる期間の同じ取引対象の配送契約価格に基づいて,両価格の価格差が大きい場合,クロス期間の仲介のために異なる期間の先物契約を同時に購入・販売することができます.商品先物と同様に,デジタル通貨もクロス期間の仲介契約ポートフォリオを持っています.例えば,OKEX取引所で,以下があります: ETC 現週,ETC 来週,ETC 四半期. 例えば,当週のETCとETCの四半期間の価格差が長期間約5にとどまると仮定します.価格差が1日7に達すると,将来的には価格差が5に戻ると予想します.その後,当週ETCを売却し,同時期にETC四半期を購入して価格差をショートすることができます.その反対に.この価格差が存在しているにもかかわらず,手動手動操作,精度低下,価格変動の影響により手動仲介には多くの不確実性があります.定量仲介の魅力は,定量モデルや仲介取引戦略の策定を通じて仲介機会を把握し,また,プログラムされたアルゴリズムを通じて取引所に自動的に取引オーダーを置き,機会を迅速かつ正確に把握し,効率的かつ安定的に利益を得ることにあります.
この記事では,FMZ量子取引プラットフォームとOKEX取引所のETC先物契約の使い方を教え,即時の仲介機会を把握し,毎回見られる利益を把握し,簡単な仲介戦略でデジタル通貨取引で遭遇するリスクをヘッジする方法を示します.
難しさ: 普通
上記はデジタル通貨のクロス・ペリオド・アビトラージ戦略の単純な論理説明です. では,このプログラムで私たちのアイデアをどのように実装しますか? 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
}
}
戦略の枠組みは,戦略のアイデアとトランザクションプロセスに従って簡単に設定できます. 戦略全体が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回しか実行されない,トランザクション前の処理前のコードを実行します.
//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
}
デジタル通貨の簡単なクロス・ペリオド・アービタージ戦略を 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
この記事の戦略は単なる例です. 本物のボットは簡単ではありませんが,その例をたどり,自分の野蛮な想像力を使用することができます. 私の限られた経験に基づいて,現在のデジタル通貨市場で,ほとんどすべての純粋な先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物先物 理由は,どのデジタル通貨交換先物市場であろうと,その利回りは法定通貨ではない. 現時点では,ほぼすべてのデジタル通貨は年初から約70%減少しています. つまり,戦略は常に通貨を稼ぐことですが,通貨価格は減少しています. 全体として,デジタル通貨市場はブロックチェーンから切り離されたようです. 当時,チューリップのように,価格は常に人々の期待と信頼から来ています. そして信頼は価格から来ています...