最後の章の内容をさらに説明しましょう (https://www.fmz.com/bbs-topic/9725).
3つ目の追加機能は
self.balanceAccount = function() {
var account = exchange.GetAccount()
if (!account) {
return
}
self.account = account
var now = new Date().getTime()
if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {
self.preCalc = now
var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
}
self.btc = account.Stocks
self.cny = account.Balance
self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
var balanced = false
if (self.p < 0.48) {
Log ( \"\" Start Balance \"\", self. P)
self.cny -= 300
if (self.orderBook.Bids.length >0) {
exchange.Buy(self.orderBook.Bids[0].Price + 0.00, 0.01)
exchange.Buy(self.orderBook.Bids[0].Price + 0.01, 0.01)
exchange.Buy(self.orderBook.Bids[0].Price + 0.02, 0.01)
}
} else if (self.p > 0.52) {
Log ( \"\" Start Balance \"\", self. P)
self.btc -= 0.03
if (self.orderBook.Asks.length >0) {
exchange.Sell(self.orderBook.Asks[0].Price - 0.00, 0.01)
exchange.Sell(self.orderBook.Asks[0].Price - 0.01, 0.01)
exchange.Sell(self.orderBook.Asks[0].Price - 0.02, 0.01)
}
}
Sleep(BalanceTimeout)
var orders = exchange.GetOrders()
if (orders) {
for (var i = 0; i < orders.length; i++) {
if (orders[i].Id != self.tradeOrderId) {
exchange.CancelOrder(orders[i].Id)
}
}
}
}
設計者がLeeksReaper ()
対象を構成し,balanceAccount ()
対象に追加された機能は,アカウントに保存されている資産情報を更新します.self.account
つまり,account
建設対象の属性. 収益値を計算し,それを時間内にプリントします. その後,最新のアカウント資産情報に従って,スポット通貨残高比率 (スポットポジション残高) を計算し,オフセットしきい値をトリガーするときに,小さなオーダーでポジションを閉じ,通貨 (ポジション) を均衡状態に戻す. 取引に一定の時間を待って,その後すべてのメーカーをキャンセルします. 機能の実行の次のラウンドでは,残高を確認し,対応する処理を再開します.
この関数のコードを文ごとに見てみましょう.
まず,最初の文var account = exchange.GetAccount ()
ローカル変数を宣言する.account
と関数を呼び出しますexchange.GetAccount
変数に割り当てるaccount
変数を判断する.account
変数がnull
(例えば,タイムアウト,ネットワーク,交換インターフェイス例外,など),それは返します (対応するif (!account) {...}
) 直接
self.account = account
ローカル変数を割り当てることです.account
についてaccount
構成されたオブジェクトの属性で,構成されたオブジェクトに最新のアカウント情報を記録する.
Var now = new Date().getTime ()
ローカル変数を宣言する.now
呼び出しますgetTime()
JavaScript languagenow
.
if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)){...}
現在のタイムスタンプと最後に記録されたタイムスタンプの間の差がパラメータを超えると決定します.CalcNet Interval * 1000
更新されたことを意味します. これまでは,更新された数を上回っています.CalcNetInterval * 1000
ミリ秒 (CalcNetInterval
印刷収入を定期的に計算する. 印刷収入の価格が収入を計算するために使用されるため,self.orderBook.Bids.length > 0
if 文の条件が起動すると,if 文の条件が実行されます.if 文の条件が起動すると,if 文の条件が実行されます.if 文の条件が起動すると,if 文の条件が実行されます.if 文の条件が起動すると,if 文の条件が実行されます.if 文の条件が起動すると,if 文の条件が実行されます.if 文の条件が起動すると,if 文の条件が実行されます.if 文の条件が起動すると,if 文の条件が実行されます.if 文の条件が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.if 文が起動すると,if 文が起動します.ifself.PreCalc = now
最新印刷されたリターンのタイムスタンプ変数を更新するために実行されます.self.preCalc
現在のタイムスタンプまでnow
収益統計では,純価値計算方法が用いられます.コードはvar net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
,つまり,現在の購入価格に従って通貨を貨幣に変換 (通貨) を1つ,それから口座の金額にそれを追加し,宣言したローカル変数に割り当てますnet
現在の総純価値が前回記録された総純価値と一致するかどうかを判断します.
if (net != self.preNet) {
self.preNet = net
LogProfit(net)
}
もしそれが一貫していないなら,net! = self.preNet
true は true の属性を更新します.self.preNet
変数による純価値の記録に使用されます.net
. その後,合計 netto をプリントnet
FMZ 量子取引プラットフォームロボット (FMT) の収益率曲線図にLogProfit
FMZ API ドキュメントでクエリすることができます).
収入の定期的な印刷が起動しない場合は,次のプロセスを続け,account.Stocks
(現行口座に現金がある) とaccount.Balance
流通口座に現金 (現金) があり,self.BTC
そしてself.CNY
. 偏移スケールを計算し,割り当てを記録します.self.p
.
self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
アルゴリズムもとてもシンプルで 通貨の現在の価値の割合を 口座の総純価値に計算します
お金バランス (ポジション) を起動するタイミングを判断する場合はどうでしょうか?
バッファーを超えたバランスを実行します. つまり,もし,このバッファーを超えたバランスを実行すると,self.p < 0.48
市場開通時の購入ポジションから毎回0.01値上がりし,3つの小規模なオーダーが配列されます.同様に,貨幣バランスでは,価格が0.01値上がりします.self.p > 0.52
1枚を売り,小規模な注文をリリースします. 最後に,すべての注文をキャンセルしますSleep(BalanceTimeout)
パラメータ設定に従って一定の時間.
Var orders = exchange. Get Orders () # Get all current makers, with orders variable
If (orders) { # If the variable orders used to obtain the current order data is not null
for (var i = 0; i < orders.length; I + +) { # Loop through orders and cancel orders one by one
if (orders[i].Id != self.tradeOrderId) {
Exchange. CancelOrder (orders [I]. Id) # Call exchange. CancelOrder to cancel orders based on orders [I]. Id
}
}
}
4つ目の追加機能は
戦略の核心部分には 主要なゲームがありますself.poll = function(){...}
戦略全体の主要な論理です 前回の記事で述べたようにmain()
実行を開始し,無限に入力します.while
ループは,我々は使用しますvar reaper = LeeksReaper()
ループの呼び出しを実行します. ループの呼び出しは,reaper.poll()
についてmain()
function.
についてself.poll
ループごとに準備作業を行います. ループは,ループの各部分で実行されます.self.numTick++
増やして 増やしてself.updateTrades()
最近の市場取引記録を更新し,関連する利用データを計算します.self.updateOrderBook()
注文データを更新し,関連するデータを計算します.self.balanceAccount()
お金 (ポジション) の残高をチェックする.
Var burstPrice = self. Prices [self. Prices. Length-1] * BurstThresholdPct # Calculate Burst Price
Var bull = false # Declare a bull-marked variable, initially false
Var bear = false # Declare a bear marked variable, initially false
Var tradeAmount = 0 # Declare the transaction amount variable, initially 0
次のステップは,現在の短期市場が牛なのか熊なのか判断することです.
if (self.numTick > 2 && (
self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -1)) > burstPrice ||
self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -2)) > burstPrice && self.prices[self.prices.length-1] > self.prices[self.prices.length-2]
)) {
bull = true
tradeAmount = self.cny / self.bidPrice * 0.99
} else if (self.numTick > 2 && (
self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -1)) < -burstPrice ||
self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -2)) < -burstPrice && self.prices[self.prices.length-1] < self.prices[self.prices.length-2]
)) {
bear = true
tradeAmount = self.btc
}
覚えてる?self.updateOrderBook()
時間順序で計算した値です. 計算した値の平均値はprices
3つの新しい機能:_.min
, _.max
そしてslice
簡単に理解できるものです
· _. min
: パラメータ配列の最小値を求めることです.
· _.max
: パラメータ配列の最大値を見つけることです.
· slice
: 機能はJavaScript
配列オブジェクト. これは,指数に従って配列の一部を返すのに使用されます.例えば:
function main() {
// index .. -8 -7 -6 -5 -4 -3 -2 -1
var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Log (arr. Slice (-5, -1)) // it will intercept the elements from 4 to 1 and return a new array: [4,3,2,1]
}
熊市場と牛市場を判断する条件は次のとおりです.
■ 地域社会self.numTick > 2
つまり,新しい検知価格ラウンドが始まると,少なくとも3回検知ラウンド後に起動し,最初から起動しないようにする必要があります.
■ 過去のデータとの差self.prices
最新のデータと,前回の範囲の最大または最低価格self.prices
価格を上回る必要があります.burstPrice
.
すべての条件が正しい場合,マークbull
またはbear
変数に値を代入します.tradeAmount
スタッドの取引を計画する
結論から言うとself.vol
更新され,前回のデータで計算されました.self.updateTrades()
機能やBurstThresholdVol
パラメータは,トランザクション強度を減らすかどうかを決定する (計画されたトランザクション量を減らす).
if (self.vol < BurstThresholdVol) {
TradeAmount * = self. Vol/BurstThresholdVol //Reduce the planned volume by self. Vol/BurstThresholdVol times of the previous volume
}
if (self.numTick < 5) {
TradeAmount * = 0.8 // reduced to 80% of the plan
}
If (self. NumTick < 10) { // reduce to 80% of the plan
tradeAmount *= 0.8
}
次に,取引信号とボリュームが要件を満たしているか判断します.
If ( (!Bull && !Bear) | | tradeAmount < MinStock) { # If it is not a bull market and not a bear market, or the amount tradeAmount planned to trade is less than the minimum trading volume MinStock set by the parameter, the poll function returns without trading operations directly
return
}
上記の判決の後,執行するvar tradePrice = bull ? self.bidPrice: self.askPrice
取引価格を,熊市場か牛市場かによって設定し,対応する konosament価格と値を割り当てます.
そして最後に,while
ループを停止する唯一の条件は,計画された取引量がtradeAmount > = MinStock
最低の取引量より低い場合
ループでは,注文は現在の市場状態に従って実行されます. そして変数に注文IDを記録します.orderId
. Sleep(200)
ループは,ループの各ループに注文を出す後200ミリ秒間待っています.ループは,ループの各ループに注文を出す後に,ループの各ループに命令を出すことを決定します.orderId
true である場合 (order ID が返されず,if 条件が起動しない場合). condition が true である場合. order ID を取得し,self.tradeOrderId
.
変数を宣言するorder
注文データを保存するために使用され,初期値はnull
. その後,IDの順序データはループで取得され,その順序がメーカーの状態であるかどうかを判断します. そうであれば,IDの順序はキャンセルされ,そうでなければ検出ループは終了します.
Var order = null // Declare a variable to hold the order data
While (true) { // a while loop
Order = exchange. GetOrder (orderId) // Call GetOrder to query the order data whose order ID is orderId
If (order) { // If the order data is queried and the query fails and the order is null, the current if condition will not be triggered
If (order. Status = = ORDER _ STATE _ PENDING) { // Judge whether the order status is maker
Exchange. CancelOrder (orderId) // If the order is maker, cancel the order
Sleep(200)
} else { // otherwise execute break to end the current while loop
break
}
}
}
次に次の手順を実行します.
Self. TradeOrderId = 0 // Reset self. TradeOrderId.
TradeAmount-= order. DealAmount // Update tradeAmount, subtract the quantity of the order on the bill of lading that has been completed
TradeAmount * = 0.9 //Decrease the order amount
If (order. Status = = ORDER _ STATE _ CANCELED) { // if the order is already cancelled
Self. UpdateOrderBook () // Update data such as order book
While (bull & & self. BidPrice-tradePrice > 0.1) { // In a bull market, if the updated bill of lading price exceeds the current trading price by 0.1, the trading amount will be reduced and the trading price will be adjusted slightly
tradeAmount *= 0.99
tradePrice += 0.1
}
While (bear & & self. AskPrice-tradePrice < -0.1) { // In a bear market, if the updated bill of lading price exceeds the current trading price by 0.1, the trading amount will be reduced and the trading price will be adjusted slightly
tradeAmount *= 0.99
tradePrice -= 0.1
}
}
プログラムプロセスが終了するとwhile (tradeAmount > = MinStock){...}
この価格爆発取引の実行が完了したことを示します.
実行するself.numTick = 0
,つまり,リセットします.self.numTick
0 にする
についてLeeksReaper()
構成要素が返します.self
実行終了時に,つまりvar reaper = LeeksReaper()
返却されます.reaper
.
分析したところ,LeeksReaper()
この記事を読むと,この高周波戦略アルゴリズムプロセスの明確な理解を得られると信じています.