Estratégia de ordem pendente equilibrada (estratégia de ensino)

Autora:Lydia., Criado: 2022-12-19 17:19:44, Atualizado: 2023-09-20 10:01:27

img

Estratégia de ordem pendente equilibrada (estratégia de ensino)

A essência da estratégia descrita neste artigo é uma estratégia de balanço dinâmico, ou seja, o valor da moeda do saldo é sempre igual ao valor da moeda de avaliação.

  • Encapsulamento lógico da estratégia Encapsular a lógica da estratégia com alguns dados e variáveis de tag no tempo de execução (encapsulado como objetos).

  • Código para inicialização do processamento de estratégias A informação inicial da conta é registrada na execução inicial para o cálculo de lucro.

  • Código para o processamento de interações de estratégia É concebido um simples processamento interativo de pausa e retomada.

  • Código para o cálculo do lucro da estratégia O método de cálculo padrão de moeda é utilizado para calcular o lucro.

  • Mecanismo de persistência dos dados chave na estratégia Projeto de mecanismos de recuperação de dados.

  • Código para exibição das informações de processamento da estratégia Exibição de dados da barra de estado.

Código de estratégia

var Shannon = {
    // member
    e : exchanges[0],
    arrPlanOrders : [],
    distance : BalanceDistance,
    account : null,
    ticker : null, 
    initAccount : null,
    isAskPending : false,
    isBidPending : false,

    // function 
    CancelAllOrders : function (e) {
        while(true) {
            var orders = _C(e.GetOrders)
            if(orders.length == 0) {
                return 
            }
            Sleep(500)
            for(var i = 0; i < orders.length; i++) {
                e.CancelOrder(orders[i].Id, orders[i])
                Sleep(500)
            }
        }
    },

    Balance : function () {
        if (this.arrPlanOrders.length == 0) {
            this.CancelAllOrders(this.e)
            var acc = _C(this.e.GetAccount)
            this.account = acc
            var askPendingPrice = (this.distance + acc.Balance) / acc.Stocks
            var bidPendingPrice = (acc.Balance - this.distance) / acc.Stocks
            var askPendingAmount = this.distance / 2 / askPendingPrice
            var bidPendingAmount = this.distance / 2 / bidPendingPrice

            this.arrPlanOrders.push({tradeType : "ask", price : askPendingPrice, amount : askPendingAmount}) 
            this.arrPlanOrders.push({tradeType : "bid", price : bidPendingPrice, amount : bidPendingAmount})
        } else if(this.isAskPending == false && this.isBidPending == false) {
            for(var i = 0; i < this.arrPlanOrders.length; i++) {
                var tradeFun = this.arrPlanOrders[i].tradeType == "ask" ? this.e.Sell : this.e.Buy
                var id = tradeFun(this.arrPlanOrders[i].price, this.arrPlanOrders[i].amount)
                if(id) {
                    this.isAskPending = this.arrPlanOrders[i].tradeType == "ask" ? true : this.isAskPending
                    this.isBidPending = this.arrPlanOrders[i].tradeType == "bid" ? true : this.isBidPending
                } else {
                    Log("Pending order failed, clear!")
                    this.CancelAllOrders(this.e)
                    return 
                }
            }
        }

        if(this.isBidPending || this.isAskPending) {
            var orders = _C(this.e.GetOrders)
            Sleep(1000)
            var ticker = _C(this.e.GetTicker)
            this.ticker = ticker
            if(this.isAskPending) {
                var isFoundAsk = false 
                for (var i = 0; i < orders.length; i++) {
                    if(orders[i].Type == ORDER_TYPE_SELL) {
                        isFoundAsk = true
                    }
                }
                if(!isFoundAsk) {
                    Log("Selling order filled, cancel the order, reset")
                    this.CancelAllOrders(this.e)
                    this.arrPlanOrders = []
                    this.isAskPending = false 
                    this.isBidPending = false 
                    LogProfit(this.CalcProfit(ticker))
                    return 
                }
            }
            if(this.isBidPending) {
                var isFoundBid = false 
                for(var i = 0; i < orders.length; i++) {
                    if(orders[i].Type == ORDER_TYPE_BUY) {
                        isFoundBid = true
                    }
                }
                if(!isFoundBid) {
                    Log("Buying order filled, cancel the order, reset")
                    this.CancelAllOrders(this.e)
                    this.arrPlanOrders = []
                    this.isAskPending = false 
                    this.isBidPending = false 
                    LogProfit(this.CalcProfit(ticker))
                    return 
                }
            }        
        }
    }, 
    ShowTab : function() {
        var tblPlanOrders = {
            type : "table", 
            title : "Plan pending orders", 
            cols : ["direction", "price", "amount"], 
            rows : []
        }
        for(var i = 0; i < this.arrPlanOrders.length; i++) {
            tblPlanOrders.rows.push([this.arrPlanOrders[i].tradeType, this.arrPlanOrders[i].price, this.arrPlanOrders[i].amount])
        }

        var tblAcc = {
            type : "table", 
            title : "Account information", 
            cols : ["type", "Stocks", "FrozenStocks", "Balance", "FrozenBalance"], 
            rows : []            
        }
        tblAcc.rows.push(["Initial", this.initAccount.Stocks, this.initAccount.FrozenStocks, this.initAccount.Balance, this.initAccount.FrozenBalance])
        tblAcc.rows.push(["This", this.account.Stocks, this.account.FrozenStocks, this.account.Balance, this.account.FrozenBalance])
        
        return "Time:" + _D() + "\n `" + JSON.stringify([tblPlanOrders, tblAcc]) + "`" + "\n" + "ticker:" + JSON.stringify(this.ticker)
    },
    CalcProfit : function(ticker) {
        var acc = _C(this.e.GetAccount)
        this.account = acc
        return (this.account.Balance - this.initAccount.Balance) + (this.account.Stocks - this.initAccount.Stocks) * ticker.Last
    },
    Init : function() {
        this.initAccount = _C(this.e.GetAccount)
        if(IsReset) {
            var acc = _G("account")
            if(acc) {
                this.initAccount = acc 
            } else {
                Log("Failed to restore initial account information! Running in initial state!")
                _G("account", this.initAccount)
            }
        } else {
            _G("account", this.initAccount)
            LogReset(1)
            LogProfitReset()
        }
    },
    Exit : function() {
        Log("Cancel all pending orders before stopping...")
        this.CancelAllOrders(this.e)
    }
}

function main() {
    // Initialization
    Shannon.Init()

    // Main loop
    while(true) {
        Shannon.Balance()        
        LogStatus(Shannon.ShowTab())
        // Interaction
        var cmd = GetCommand()
        if(cmd) {
            if(cmd == "stop") {
                while(true) {
                    LogStatus("Pause", Shannon.ShowTab())
                    cmd = GetCommand()
                    if(cmd) {
                        if(cmd == "continue") {
                            break
                        }
                    }
                    Sleep(1000)
                }
            }
        }
        Sleep(5000)
    }
}

function onexit() {
    Shannon.Exit()
}

Testes de retrocesso

img img img img

Optimização e extensão

  • Alguns mercados têm preços limitados em ordens pendentes, então a ordem pode não ser efetivamente colocada.
  • Adicione a negociação de futuros.
  • Expandir uma versão multi-espécie e multi-intercâmbio.

As estratégias são apenas para fins educacionais e devem ser usadas com cautela na negociação de bots reais. Endereço estratégico:https://www.fmz.com/strategy/225746


Relacionados

Mais.