続きを進めよう前回の内容説明するために
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 to 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 to 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()
FMZ API インターフェイスで,現在の口座の最新のデータを取得し,変数に割り当てaccount
変数を判断する.account
変数の値がnull
(タイムアウト,ネットワーク,プラットフォームインターフェース例外など) のような変数を取得できなければ,直接 (対応する) 返します.if (!account ){...}
このページです)
声明self.account = account
ローカル変数を割り当てることです.account
属性に対してaccount
建設されたオブジェクトの最新アカウント情報を記録する.
声明var now = new Date().getTime()
ローカル変数を宣言する.now
呼び出しますgetTime()
JavaScript言語の時間&日付オブジェクトの関数で,現在のタイムスタンプを返し,変数にタイムスタンプを割り当てますnow
.
コード:if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {...}
現在のタイムスタンプと最後に記録されたタイムスタンプの違いを判断します.値がパラメータを超えると,CalcNetInterval * 1000
超えたことを意味します.CalcNetInterval * 1000
ミリ秒 (CalcNetInterval
利益を計算する際に市場での1購入価格を使用する必要があるため,条件は,条件に限定されています.self.orderBook.Bids.length > 0
(深度データ,購入注文リストでレベル情報として有効である必要があります).
命令の条件 self.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 で,属性を更新します.self.preNet
純価値を記録するnet
そして,総純価値のデータを印刷します.net
FMZ 量子取引プラットフォームのボットの利益曲線グラフに (あなたは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上昇するたびに,通貨残高が0.01上昇します.self.p > 0.52
市場で販売 1 価格の小さな注文を待ち. 最後に,パラメータ設定に従って,一定の期間を待つ.Sleep(BalanceTimeout)
オーダーをキャンセルします
var orders = exchange.GetOrders() # obtain all the current pending orders, and save them in the variable orders"
if (orders) { # if the variable "orders", which obtains all the current pending orders, is not null
for (var i = 0; i < orders.length; i++) { # use the loop to traverse "orders", and cancel the orders one by one
if (orders[i].Id != self.tradeOrderId) {
exchange.CancelOrder(orders[i].Id) # call "exchange.CancelOrder", and cancel orders by "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 the burst price
var bull = false # declare the variable marked by the bull market; the initial value is false
var bear = false # declare the variable marked by the bear market; the initial value is false
var tradeAmount = 0 # declare the variable of trading amount; the initial value is 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 several 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
とtrue
変数に値を代入します.tradeAmount
交換を計画する
このパラメータは,BurstThresholdVol
基準として,self.vol
更新され,前回のデータで計算されました.self.updateTrades()
取引の強度 (計画された取引量を減らす) を決定する.
if (self.vol < BurstThresholdVol) {
tradeAmount *= self.vol / BurstThresholdVol // reduce the planned trading volume, and reduce it to the previous volume multiplied by "self.vol / BurstThresholdVol"
}
if (self.numTick < 5) {
tradeAmount *= 0.8 // reduced to 80% of the plan
}
if (self.numTick < 10) { // reduced to 80% of the plan
tradeAmount *= 0.8
}
次に,取引信号と取引量が要件を満たしているか判断します.
if ((!bull && !bear) || tradeAmount < MinStock) { # if it is not a bull market nor a bear market, or the planned trading volume "tradeAmount" is less than the minimum trading volume "MinStock" set by the parameter, the "poll" function returns directly without any trading operation
return
}
上記の判決の後,執行するvar tradePrice = bull ? self.bidPrice : self.askPrice
熊市場か牛市場かによって,取引価格を設定し,対応する配達注文価格に値を割り当てます.
最後に,入力してくださいwhile
ループの唯一の停止とブレークアウト条件はtradeAmount >= MinStock
つまり,計画された取引量は最低取引量より少ない.
ループでは,現在の牛市場状態または熊市場状態に応じて,注文を実行します. そして変数に注文IDを記録します.orderId
処刑するSleep(200)
ループは,各ラウンドで注文をすると200ミリ秒間待っています.orderId
true である場合 (order ID が返されず,条件が起動しない場合). condition が true である場合,order ID を取得し,self.tradeOrderId
.
変数を宣言するorder
初期値で注文データを保存するnull
. その後,ループを使用して,IDで注文データを取得し,注文が待ち受けている注文状態にあるかどうかを決定します.
var order = null // declare a variable to save the order data
while (true) { // a while loop
order = exchange.GetOrder(orderId) // call "GetOrder" to query the order data with the ID of orderId
if (order) { // if the order data is queried,and the query fails, the order is null, and "if" will not be triggered
if (order.Status == ORDER_STATE_PENDING) { // judge whether the current order status is pending order
exchange.CancelOrder(orderId) // if the current order status is pending order, cancel the order
Sleep(200)
} else { // if not, execute "break" to break out of the while loop
break
}
}
}
次に次の手順を実行します.
self.tradeOrderId = 0 // reset "self.tradeOrderId"
tradeAmount -= order.DealAmount // update "tradeAmount", and subtract the executed amount of the orders in the delivery order
tradeAmount *= 0.9 // reduce the intensity of ordering
if (order.Status == ORDER_STATE_CANCELED) { // if the order is canceled
self.updateOrderBook() // update the data, including the order book data
while (bull && self.bidPrice - tradePrice > 0.1) { // in a bull market, if the updated bid price exceeds the current trading price by 0.1, reduce the trading intensity, and slightly adjust the trading price
tradeAmount *= 0.99
tradePrice += 0.1
}
while (bear && self.askPrice - tradePrice < -0.1) { // in a bear market, if the updated ask price exceeds the current trading price by 0.1, reduce the trading intensity, and slightly adjust the trading price
tradePrice -= 0.1
}
}
プログラムフローがwhile (tradeAmount >= MinStock) {...}
ループは,価格爆発取引の実行が完了することを意味します.
実行するself.numTick = 0
つまり,リセットself.numTick
0 にする
建設者の最後の実行LeeksReaper()
を返します.self
対象となる場合です.var reaper = LeeksReaper()
,オブジェクトは戻されます.reaper
.
分析したところ,LeeksReaper()
このコンストラクタは,このプロフィットハーベスターオブジェクト,オブジェクトの様々な方法,および主要な論理関数の実行プロセスを構築します. この記事を読んだ後,あなたは高周波戦略アルゴリズムプロセスについてより明確に理解できると思います.