菜食機戦略解剖 (1)

作者: リン・ハーン小さな夢, 作成日:2020年11月12日 22:11:32, 更新日:2023年9月26日 21:04:43

img

菜食機の戦略分析

最近の微信群での発明者定量化に関する議論print moneyロボットについて,非常に熱烈な議論が繰り広げられ,非常に古い戦略が再び広場客たちの視野に入ってきた.菜食機print moneyロボット取引の原理は,菜刈り機の戦略を借用し,当時菜刈り機の戦略について十分に理解していないと非難した.OKCoinを移植する│ │ 開発者は,プラットフォームの移植版のカバノキ刈り機戦略を量化し,その戦略を分析し,その戦略のアイデアを掘り出す. この記事では,戦略的考えや意図などのレベルを分析し,プログラミングに関連する退屈な内容を最小限に抑えるようにしています.

[OKCoinを移植する菜刈り機] 戦略 ソースコード:

function LeeksReaper() {
    var self = {}
    self.numTick = 0
    self.lastTradeId = 0
    self.vol = 0
    self.askPrice = 0
    self.bidPrice = 0
    self.orderBook = {Asks:[], Bids:[]}
    self.prices = []
    self.tradeOrderId = 0
    self.p = 0.5
    self.account = null
    self.preCalc = 0
    self.preNet = 0

    self.updateTrades = function() {
        var trades = _C(exchange.GetTrades)
        if (self.prices.length == 0) {
            while (trades.length == 0) {
                trades = trades.concat(_C(exchange.GetTrades))
            }
            for (var i = 0; i < 15; i++) {
                self.prices[i] = trades[trades.length - 1].Price
            }
        }
        self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) {
            // Huobi not support trade.Id
            if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
                self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
                mem += trade.Amount
            }
            return mem
        }, 0)

    }
    self.updateOrderBook = function() {
        var orderBook = _C(exchange.GetDepth)
        self.orderBook = orderBook
        if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
            return
        }
        self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
        self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
        self.prices.shift()
        self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.35 +
            (orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
            (orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.05))
    }
    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("开始平衡", 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("开始平衡", 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)
                }
            }
        }
    }

    self.poll = function() {
        self.numTick++
        self.updateTrades()
        self.updateOrderBook()
        self.balanceAccount()
        
        var burstPrice = self.prices[self.prices.length-1] * BurstThresholdPct
        var bull = false
        var bear = false
        var tradeAmount = 0
        if (self.account) {
            LogStatus(self.account, 'Tick:', self.numTick, ', lastPrice:', self.prices[self.prices.length-1], ', burstPrice: ', burstPrice)
        }
        
        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
        }
        if (self.vol < BurstThresholdVol) {
            tradeAmount *= self.vol / BurstThresholdVol
        }
        
        if (self.numTick < 5) {
            tradeAmount *= 0.8
        }
        
        if (self.numTick < 10) {
            tradeAmount *= 0.8
        }
        
        if ((!bull && !bear) || tradeAmount < MinStock) {
            return
        }
        var tradePrice = bull ? self.bidPrice : self.askPrice
        while (tradeAmount >= MinStock) {
            var orderId = bull ? exchange.Buy(self.bidPrice, tradeAmount) : exchange.Sell(self.askPrice, tradeAmount)
            Sleep(200)
            if (orderId) {
                self.tradeOrderId = orderId
                var order = null
                while (true) {
                    order = exchange.GetOrder(orderId)
                    if (order) {
                        if (order.Status == ORDER_STATE_PENDING) {
                            exchange.CancelOrder(orderId)
                            Sleep(200)
                        } else {
                            break
                        }
                    }
                }
                self.tradeOrderId = 0
                tradeAmount -= order.DealAmount
                tradeAmount *= 0.9
                if (order.Status == ORDER_STATE_CANCELED) {
                    self.updateOrderBook()
                    while (bull && self.bidPrice - tradePrice > 0.1) {
                        tradeAmount *= 0.99
                        tradePrice += 0.1
                    }
                    while (bear && self.askPrice - tradePrice < -0.1) {
                        tradeAmount *= 0.99
                        tradePrice -= 0.1
                    }
                }
            }
        }
        self.numTick = 0
    }
    return self
}

function main() {
    var reaper = LeeksReaper()
    while (true) {
        reaper.poll()
        Sleep(TickInterval)
    }
}

戦略の概要

一般的に,戦略を学ぶとき,読むとき,まず全体的なプログラム構造を見てください. この戦略コードはあまり多くありません,200行未満のコードで,非常に簡潔で,元のバージョンの戦略還元が非常に高く,基本的には同じです.main()実行を開始します.main()メディアは,LeeksReaper()この関数は,LeeksReaper()関数もよく理解できます. この関数は,カバノキの戦略論理モジュール (一つのオブジェクト) の構築関数として理解できます.LeeksReaper()リンゴ刈り機の取引論理を構築する責任者.

キーワード:img img

  • 戦略main函数の一行目:var reaper = LeeksReaper()ローカル変数を宣言します.reaperLeeksReaper () が実行される場合,この LeeksReaper () は,reaper

  • 戦略mainこの関数は次のようになります.

    while (true) {
        reaper.poll()
        Sleep(TickInterval)
    }
    

    移動するwhile死のサイクル 絶え間ない実行reaperオブジェクトの処理関数poll()poll()函数が取引戦略の主要な論理であるとき,その戦略プロセスは取引の論理を絶えず実行するようになります. についてSleep(TickInterval)この行は,取引論理の回転頻度を制御するために,全体的な取引論理が実行されるたびに停止時間を制御することをよく理解しています.

解剖LeeksReaper()構造関数

見てくださいLeeksReaper()戦略論理オブジェクトをどのように構成するか.

LeeksReaper()任意の項目を表示します.var self = {}ありがとうございました.LeeksReaper()この空のオブジェクトにいくつかの方法や属性を徐々に追加し,最終的にこのオブジェクトの構築を完了し,最終的にこのオブジェクトを返します.main()この関数には,var reaper = LeeksReaper()このステップでは,返されたオブジェクトの値がreaper)。

ほらselfオブジェクトの属性追加

このビデオはself多くの属性が追加され,それぞれの属性が説明され,その属性,変数の用途,意図,戦略を簡単に理解し,このコードの堆積物を見ないために,その属性をすぐに理解することができます.

    self.numTick = 0         # 用来记录poll函数调用时未触发交易的次数,当触发下单并且下单逻辑执行完时,self.numTick重置为0
    self.lastTradeId = 0     # 交易市场已经成交的订单交易记录ID,这个变量记录市场当前最新的成交记录ID
    self.vol = 0             # 通过加权平均计算之后的市场每次考察时成交量参考(每次循环获取一次市场行情数据,可以理解为考察了行情一次)
    self.askPrice = 0        # 卖单提单价格,可以理解为策略通过计算后将要挂卖单的价格
    self.bidPrice = 0        # 买单提单价格
    self.orderBook = {Asks:[], Bids:[]}    # 记录当前获取的订单薄数据,即深度数据(卖一...卖n,买一...买n)
    self.prices = []                       # 一个数组,记录订单薄中前三档加权平均计算之后的时间序列上的价格,简单说就是每次储存计算得到的订单薄前三档加权平均价格,放在一个数组中,用于后续策略交易信号参考,所以该变量名是prices,复数形式,表示一组价格
    self.tradeOrderId = 0    # 记录当前提单下单后的订单ID
    self.p = 0.5             # 仓位比重,币的价值正好占总资产价值的一半时,该值为0.5,即平衡状态
    self.account = null      # 记录账户资产数据,由GetAccount()函数返回数据
    self.preCalc = 0         # 记录最近一次计算收益时的时间戳,单位毫秒,用于控制收益计算部分代码触发执行的频率
    self.preNet = 0          # 记录当前收益数值

ほらselfオブジェクトの追加方法

セルフにこれらの属性を追加すると,selfオブジェクトは,特定の作業や機能を行うために方法を追加します.

この関数には,次の関数があります.

    self.updateTrades = function() {
        var trades = _C(exchange.GetTrades)  # 调用FMZ封装的接口GetTrades,获取当前最新的市场成交数据
        if (self.prices.length == 0) {       # 当self.prices.length == 0时,需要给self.prices数组填充数值,只有策略启动运行时才会触发
            while (trades.length == 0) {     # 如果近期市场上没有更新的成交记录,这个while循环会一直执行,直到有最新成交数据,更新trades变量
                trades = trades.concat(_C(exchange.GetTrades))   # concat 是JS数组类型的一个方法,用来拼接两个数组,这里就是把“trades”数组和“_C(exchange.GetTrades)”返回的数组数据拼接成一个数组
            }
            for (var i = 0; i < 15; i++) {   # 给self.prices填充数据,填充15个最新成交价格
                self.prices[i] = trades[trades.length - 1].Price
            }
        }
        self.vol = 0.7 * self.vol + 0.3 * _.reduce(trades, function(mem, trade) {  # _.reduce 函数迭代计算,累计最新成交记录的成交量
            // Huobi not support trade.Id
            if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
                self.lastTradeId = Math.max(trade.Id == 0 ? trade.Time : trade.Id, self.lastTradeId)
                mem += trade.Amount
            }
            return mem
        }, 0)

    }

updateTradesこの関数の役割は,最新の市場取引データを入手し,そのデータに基づいていくつかの計算を行い,記録し,戦略のフォローアップの論理に使用することを提供する. この記事へのトラックバック一覧です. について_.reduceプログラミングの知識のない生徒が困惑するかもしれません._.reduceそうですUnderscore.jsこのデータベースの関数は,FMZJSのポリシーがサポートしているので,リターン計算は便利です.Underscore.js资料链接

簡単な意味もあります:

function main () {
   var arr = [1, 2, 3, 4]
   var sum = _.reduce(arr, function(ret, ele){
       ret += ele
       
       return ret
   }, 0)

   Log("sum:", sum)    # sum 等于 10
}

解き放たれるでしょう.[1, 2, 3, 4]この数字の合計は,すべての数字を合計します.trades数列内の各取引記録データには,取引記録の取引総額を合計する.self.vol = 0.7 * self.vol + 0.3 * _.reduce(...)ありがとうございました....代用するコードの山.self.volこの計算は,重度の平均である.つまり,最新の取引は総取引の30%を重み付け,前回の重み付けは70%を重み付けしている.この比率は,戦略の著者が設定したもので,おそらく市場法則の観察に関連している. 最近の取引データを取得したインターフェースが古いデータを復元したら どうなるか尋ねると,私は誤ったデータと意味のあるデータを得ています.

if ((trade.Id > self.lastTradeId) || (trade.Id == 0 && trade.Time > self.lastTradeId)) {
    ...
}

この判断は,取引記録の取引IDに基づいて判断することができ,IDが最後の記録のIDよりも大きい場合にのみ累積を誘発するか,または取引所のインターフェースがIDを提供していない場合,すなわち,trade.Id == 0取引記録の時間軸を使って判断します.self.lastTradeId取引記録の時間軸が保存されますが,IDではありません.

この関数には,次の関数があります.

    self.updateOrderBook = function() {
        var orderBook = _C(exchange.GetDepth)
        self.orderBook = orderBook
        if (orderBook.Bids.length < 3 || orderBook.Asks.length < 3) {
            return
        }
        self.bidPrice = orderBook.Bids[0].Price * 0.618 + orderBook.Asks[0].Price * 0.382 + 0.01
        self.askPrice = orderBook.Bids[0].Price * 0.382 + orderBook.Asks[0].Price * 0.618 - 0.01
        self.prices.shift()
        self.prices.push(_N((orderBook.Bids[0].Price + orderBook.Asks[0].Price) * 0.35 +
            (orderBook.Bids[1].Price + orderBook.Asks[1].Price) * 0.1 +
            (orderBook.Bids[2].Price + orderBook.Asks[2].Price) * 0.05))
    }

未来を見ようupdateOrderBookこの関数は,関数の名前の文字通りの意味からわかるように,この関数の役割は,命令薄を更新することです. そうそう,単に命令薄を更新するだけでなく,関数 FMZ のAPI関数を呼び出すことができます.GetDepth()市場注文薄データ (売る1...売るn,買う1...買うn) を取得し,self.orderBook中.次に,注文のデータ薄の購入・販売の注文が3個未満である場合は,無効関数を直接返す.

統計学者は,この2つの数字を計算した.

  • 請求料の計算 請求書価格の計算は,また加重平均計算を用いて行われ,支払いを計算する際には,購入権は 61.8% ((0.618),売却権は余分な重量 38.2% ((0.382) となり,購入権は 61.8% ((0.618),売却権は 38.2% ((0.382) となり,購入権は 61.8% ((0.618),購入権は 61.8% ((0.382) となり,購入権は 61.8% ((0.618),売却権は 38.2% ((0.382). 請求書販売単価を計算する時も同じです. 販売単価と販売単価の権利は大きいです. なぜ0.618なのかは,著者が比較的に黄金の分割比率を好む可能性がある. 最後に追加したポイントを引いたポイントの価格 ((0.01) は,略微的に再び盘口正中央から少し偏りを取るためにです.

  • 更新時間順序で注文薄前3列加重平均価格 注文薄の最初の3段の購入,販売单の価格を加重平均計算するために,最初の段重量0.7,第2段重量0.2,第3段重量0.1です. 計算してみましょう.

    (买一 + 卖一) * 0.35 + (买二 + 卖二) * 0.1 + (买三 + 卖三) * 0.05
    ->
    (买一 + 卖一) / 2 * 2 * 0.35 + (买二 + 卖二) / 2 * 2 * 0.1 + (买三 + 卖三) / 2 * 2 * 0.05
    ->
    (买一 + 卖一) / 2 * 0.7 + (买二 + 卖二) / 2 * 0.2 + (买三 + 卖三) / 2 * 0.1
    ->
    第一档平均的价格 * 0.7 + 第二档平均的价格 * 0.2 + 第三档平均的价格 * 0.1
    

    この時点で,最終的に計算された価格は,実際に反当前市場における三階層の中間盤の価格位置であることがわかります. この計算した価格で更新します.self.pricesこの式は,この式で表される.shift()更新されたデータ (※) を追加します.push()函数,shift,push は,JS言語の行列オブジェクトの方法であり,具体的にはJS資料をクエリして作成することができる.self.prices数列は時間配列の順序のデータストリームである.

咳,咳,口水を飲んで,ここで解剖して,次回はお会いしましょう.


もっと

ゆっくりと強くなる私Self.pricesは,先ず15の歴史的な取引価格を記入し,その後に,最初の3つのセットの重み付き平均価格を記入します.

スヌンプ"夢"を褒めたい

m0606悲しいことに,多くの取引所では, 取引先の価格が1つだけ残るようになっており, 取引先の価格が1つだけ残るようになっており, 取引先の価格が1つだけ残るようになっており, 取引先の価格が1つだけ残るようになっており, 取引先の価格が1つだけ残るようになっており, 取引先の価格が1つだけ残るようになっており,

ママありがとうございました. PythonのバージョンをXinjiangで実行してみました. 20枚も5分以内になくなってしまいました.

ブクシアック素晴らしい,夢の説明が全くないのに,本当に理解できない.

エディ金分割0.618 0.382は使用するフィーボ ドリーム総牛群

ほら ほら牛の群れは本当に

エヴァン1987ありがとうございました. ありがとうございました.

メイクビットドリーム総牛 p

シイイイイ牛の群れ! この記事へのトラックバック一覧です.

9つの太陽ドリーム・総,牛団!

小さな夢ほら,もういいから

小さな夢取引の頻度が高くなる可能性について知覚する.

小さな夢低周波戦略は,いくつかのサポートを必要としている. 草神によって書かれた戦略原理分析の記事を参照してください.

小さな夢ありがとうございました. 気に入ったらシェアしてください.

小さな夢ありがとうございました!

小さな夢ありがとうございました!

小さな夢ありがとうございました!

小さな夢学校に入学した頃,この黄金分割比を覚えたとき,特にはっきりと覚えているのは,この比が長方形の長方形の最も美しいことだと.

小さな夢ありがとうございました.

小さな夢この解説の比較は複雑ではなく,一行一行に可能な限り理解しやすい方法で説明されています.