O recurso está a ser carregado... Carregamento...

Estratégias binárias para a liquidez de moeda digital com várias variedades (instruções)

Autora:Inventor quantificado - sonho pequeno, Criado: 2021-12-06 17:53:51, Atualizado: 2023-09-15 20:56:36

img

Estratégias binárias para a liquidez de moeda digital com várias variedades (instruções)

De acordo com os pedidos dos usuários da comunidade, é esperado que haja uma ampla variedade de estratégias de dupla linha como referência de design. Então, esta é a época para implementar uma estratégia de dupla linha. As notas serão escritas no código da estratégia para facilitar a compreensão da estratégia, fácil de aprender.

img

Ideias estratégicas

A lógica da estratégia de dupla linha média é simples, ou seja, duas linhas médias; uma linha média com um período de parâmetros pequeno (linha rápida) e uma linha média com um período de parâmetros grande (linha lenta). Duas linhas ocorrem quando o forco de ouro (linha rápida atravessa a linha lenta de baixo) faz mais compras e duas linhas ocorrem quando o forco morto (linha rápida atravessa a linha lenta de cima para baixo) faz mais vendas.

Se a estratégia for projetada para várias variedades, então os parâmetros de cada variedade podem ser diferentes (diferentes variedades usam diferentes parâmetros da linha uniforme), então é necessário projetar os parâmetros de uma maneira que permita que o conjunto de parâmetros seja bem variável.

img

Os parâmetros são projetados em forma de strings, com intervalos de vírgulas para cada parâmetro. Ao iniciar a política, analisam-se essas strings. A lógica de execução correspondente a cada variedade (pacote de transações) é analisada. A consulta estratégica detecta o comportamento de cada variedade, o disparo de condições de transação, a impressão de gráficos, etc. Após uma consulta de todas as variedades, os dados são agregados e as informações do quadro são exibidas na barra de status.

A estratégia é muito simples e apropriada para aprendizagem inicial, com apenas 200+ linhas de código.

Código de estratégia

// 函数作用:取消当前交易对的所有挂单
function cancelAll(e) {
    while (true) {
        var orders = _C(e.GetOrders)
        if (orders.length == 0) {
            break
        } else {
            for (var i = 0 ; i < orders.length ; i++) {
                e.CancelOrder(orders[i].Id, orders[i])
                Sleep(500)
            }
        }
        Sleep(500)
    }
}

// 函数作用:计算实时收益盈亏
function getProfit(account, initAccount, lastPrices) {
    // account为当前账户信息,initAccount为初始账户信息,lastPrices为当前所有品种的最新价格
    var sum = 0
    _.each(account, function(val, key) {
        // 遍历当前所有资产,计算除了USDT以外的资产币差,以及金额差
        if (key != "USDT" && typeof(initAccount[key]) == "number" && lastPrices[key + "_USDT"]) {
            sum += (account[key] - initAccount[key]) * lastPrices[key + "_USDT"]
        }        
    })
    // 返回根据当前价格计算得出的资产盈亏
    return account["USDT"] - initAccount["USDT"] + sum
}

// 函数作用:生成图表配置
function createChartConfig(symbol, ema1Period, ema2Period) {
    // symbol为交易对,ema1Period为第一根EMA均线周期,ema2Period为第二根EMA均线周期
    var chart = {                                        
        __isStock: true,    
        extension: {
                layout: 'single', 
                height: 600, 
        },
        title : { text : symbol},                       
        xAxis: { type: 'datetime'},           
        series : [                                          
            {                                      
                type: 'candlestick',    // K线数据系列                         
                name: symbol,   
                id: symbol,
                data: []                                           
            }, {                                      
                type: 'line',           // EMA数据系列
                name: symbol + ',EMA1:' + ema1Period,          
                data: [],               
            }, {
                type: 'line',           // EMA数据系列
                name: symbol + ',EMA2:' + ema2Period,
                data: []
            }
        ]
    }
    return chart    
}

function main() {
    // 重置所有数据
    if (isReset) {
        _G(null)            // 清空所有持久化记录的数据
        LogReset(1)         // 清空所有日志
        LogProfitReset()    // 清空所有收益日志
        LogVacuum()         // 释放实盘数据库占用的资源
        Log("重置所有数据", "#FF0000")   // 打印信息
    }
    
    // 解析参数
    var arrSymbols = symbols.split(",")             // 逗号分割交易品种字符串
    var arrEma1Periods = ema1Periods.split(",")     // 分割第一根EMA均线的参数字符串
    var arrEma2Periods = ema2Periods.split(",")     // 分割第二根EMA均线的参数字符串
    var arrAmounts = orderAmounts.split(",")        // 分割每个品种的下单量
    var account = {}                                // 用于记录当前资产信息的变量
    var initAccount = {}                            // 用于记录最初资产信息的变量
    var currTradeMsg = {}                           // 用于记录当前BAR是否交易的变量
    var lastPrices = {}                             // 用于记录监控的品种最新价格的变量
    var lastBarTime = {}                            // 用于记录最近一根BAR的时间的变量,用于画图时BAR的更新判断
    var arrChartConfig = []                         // 用于记录图表配置信息,用于画图

    if (_G("currTradeMsg")) {                       // 例如重启时,恢复currTradeMsg数据
        currTradeMsg = _G("currTradeMsg")
        Log("恢复记录", currTradeMsg)
    }

    // 初始化account
    _.each(arrSymbols, function(symbol, index) {
        exchange.SetCurrency(symbol)
        var arrCurrencyName = symbol.split("_")
        var baseCurrency = arrCurrencyName[0]
        var quoteCurrency = arrCurrencyName[1]
        if (quoteCurrency != "USDT") {
            throw "only support quoteCurrency: USDT"
        }
        if (!account[baseCurrency] || !account[quoteCurrency]) {
            cancelAll(exchange)
            var acc = _C(exchange.GetAccount)
            account[baseCurrency] = acc.Stocks
            account[quoteCurrency] = acc.Balance
        }
        
        // 初始化图表相关的数据
        lastBarTime[symbol] = 0
        arrChartConfig.push(createChartConfig(symbol, arrEma1Periods[index], arrEma2Periods[index]))
    })
    if (_G("initAccount")) {
        initAccount = _G("initAccount")
        Log("恢复初始账户记录", initAccount)
    } else {
        // 用当前资产信息,初始化initAccount变量
        _.each(account, function(val, key) {
            initAccount[key] = val
        })
    }
    Log("account:", account, "initAccount:", initAccount)   // 打印资产信息

    // 初始化图表对象
    var chart = Chart(arrChartConfig)
    // 图表重置
    chart.reset()
        
    // 策略主循环逻辑
    while (true) {
        // 遍历所有品种,逐个执行双均线逻辑
        _.each(arrSymbols, function(symbol, index) {
            exchange.SetCurrency(symbol)               // 切换交易对为symbol字符串记录的交易对
            var arrCurrencyName = symbol.split("_")    // 以“_”符号分割交易对
            var baseCurrency = arrCurrencyName[0]      // 交易币的字符串
            var quoteCurrency = arrCurrencyName[1]     // 计价币的字符串

            // 根据index索引,获取当前交易对的EMA均线参数
            var ema1Period = parseFloat(arrEma1Periods[index])
            var ema2Period = parseFloat(arrEma2Periods[index])
            var amount = parseFloat(arrAmounts[index])
            
            // 获取当前交易对的K线数据
            var r = exchange.GetRecords()
            if (!r || r.length < Math.max(ema1Period, ema2Period)) {  // K线长度不足时直接返回
                Sleep(1000)
                return 
            }
            var currBarTime = r[r.length - 1].Time         // 记录当前BAR时间戳
            lastPrices[symbol] = r[r.length - 1].Close     // 记录当前最新价格

            var ema1 = TA.EMA(r, ema1Period)    // 计算EMA指标
            var ema2 = TA.EMA(r, ema2Period)    // 计算EMA指标
            if (ema1.length < 3 || ema2.length < 3) {    // EMA指标数组长度过短,直接返回
                Sleep(1000)
                return 
            }
            var ema1Last2 = ema1[ema1.length - 2]   // 倒数第二BAR上的EMA
            var ema1Last3 = ema1[ema1.length - 3]   // 倒数第三BAR上的EMA
            var ema2Last2 = ema2[ema2.length - 2]
            var ema2Last3 = ema2[ema2.length - 3]

            // 写入图表数据
            var klineIndex = index + 2 * index
            // 遍历K线数据
            for (var i = 0 ; i < r.length ; i++) {
                if (r[i].Time == lastBarTime[symbol]) {         // 画图,更新当前BAR以及指标
                    // 更新
                    chart.add(klineIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close], -1)  
                    chart.add(klineIndex + 1, [r[i].Time, ema1[i]], -1)
                    chart.add(klineIndex + 2, [r[i].Time, ema2[i]], -1)
                } else if (r[i].Time > lastBarTime[symbol]) {   // 画图,添加BAR以及指标
                    // 添加
                    lastBarTime[symbol] = r[i].Time             // 更新时间戳
                    chart.add(klineIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close])  
                    chart.add(klineIndex + 1, [r[i].Time, ema1[i]])   
                    chart.add(klineIndex + 2, [r[i].Time, ema2[i]])   
                }
            }
            
            if (ema1Last3 < ema2Last3 && ema1Last2 > ema2Last2 && currTradeMsg[symbol] != currBarTime) {
                // 金叉
                var depth = exchange.GetDepth()   // 获取当前订单薄深度数据
                var price = depth.Asks[Math.min(takeLevel, depth.Asks.length)].Price   // 取第10档价格,吃单
                if (depth && price * amount <= account[quoteCurrency]) {   // 获取深度数据正常,有足够资产下单
                    exchange.Buy(price, amount, ema1Last3, ema2Last3, ema1Last2, ema2Last2)   // 下单买入
                    cancelAll(exchange)     // 取消所有挂单
                    var acc = _C(exchange.GetAccount)   // 获取账户资产信息
                    if (acc.Stocks != account[baseCurrency]) {  // 检测账户资产发生变动
                        account[baseCurrency] = acc.Stocks      // 更新资产
                        account[quoteCurrency] = acc.Balance    // 更新资产
                        currTradeMsg[symbol] = currBarTime      // 记录当前BAR已经交易
                        _G("currTradeMsg", currTradeMsg)        // 持久化记录
                        var profit = getProfit(account, initAccount, lastPrices)  // 计算收益
                        if (profit) {
                            LogProfit(profit, account, initAccount)    // 打印收益
                        }
                    }
                }
            } else if (ema1Last3 > ema2Last3 && ema1Last2 < ema2Last2 && currTradeMsg[symbol] != currBarTime) {
                // 死叉
                var depth = exchange.GetDepth()
                var price = depth.Bids[Math.min(takeLevel, depth.Bids.length)].Price
                if (depth && amount <= account[baseCurrency]) {
                    exchange.Sell(price, amount, ema1Last3, ema2Last3, ema1Last2, ema2Last2)
                    cancelAll(exchange)
                    var acc = _C(exchange.GetAccount)
                    if (acc.Stocks != account[baseCurrency]) {
                        account[baseCurrency] = acc.Stocks
                        account[quoteCurrency] = acc.Balance
                        currTradeMsg[symbol] = currBarTime
                        _G("currTradeMsg", currTradeMsg)
                        var profit = getProfit(account, initAccount, lastPrices)
                        if (profit) {
                            LogProfit(profit, account, initAccount)
                        }
                    }
                }
            }            
            Sleep(1000)
        })

        // 状态栏表格变量
        var tbl = {
            type : "table", 
            title : "账户信息",
            cols : [], 
            rows : []
        }
        // 将数据写入状态栏表格结构
        tbl.cols.push("--")
        tbl.rows.push(["初始"])
        tbl.rows.push(["当前"])
        _.each(account, function(val, key) {
            if (typeof(initAccount[key]) == "number") {
                tbl.cols.push(key)
                tbl.rows[0].push(initAccount[key])   // 初始
                tbl.rows[1].push(val)                // 当前
            }            
        })
        // 显示状态栏表格
        LogStatus(_D(), "\n", "profit:", getProfit(account, initAccount, lastPrices), "\n", "`" + JSON.stringify(tbl) + "`")
    }
}

Revisão estratégica

img

img

img

img

Você pode ver que o ETH, o LTC e o ETC são todos desencadeados por forks de ouro e transações acontecem.

img

O teste pode ser feito através de um disco analógico.

O código da estratégia:https://www.fmz.com/strategy/333783

A estratégia é usada apenas para testes de retrospectiva, aprendizagem de estratégia de design e uso prático.


Relacionados

Mais.

Mr.Huang. 2

Mr.Huang. 2

Mr.Huang. 1

Nuvens levesObrigada Dream Big!!!

wanghehe711@qq.comObrigado obrigado! Novato está a pesquisar, mas o teste em disco real deu um erro: GetOrders: Invalid ContractType.

Inventor quantificado - sonho pequenoNão é simpático, obrigado pelo apoio.

Inventor quantificado - sonho pequenoA ideia é que este seja um exemplo de estratégia, que pode ser visto no aprendizado de código.

wanghehe711@qq.comE se eu pudesse, eu tentaria mudar isso.

Inventor quantificado - sonho pequenoA estratégia é a do momento, não de futuros.