Curso de série de investimento quantitativo Blockchain (3) Arbitragem de spread de calendário

Autora:Rubínio, Criado: 2018-08-27 16:49:50, Atualizado:

No 1 No livro Alquimia Financeira escrito por Soros em 1987, uma importante proposição foi apresentada: Eu acredito que os preços de mercado estão sempre errados no sentido de que eles apresentam uma visão tendenciosa do futuro. A hipótese de validade do mercado é apenas uma suposição teórica. Na verdade, os participantes do mercado nem sempre são racionais e, em cada momento, os participantes não podem adquirir completamente e interpretar objetivamente todas as informações. Mesmo que seja a mesma informação, o feedback de todos é diferente.

Em outras palavras, o preço em si já contém as expectativas erradas dos participantes do mercado, de modo que, em essência, o preço de mercado é sempre errado.

img

No 2 Com base nos princípios acima, sabemos também que, num mercado de futuros ineficaz, o impacto do mercado dos contratos de entrega em períodos diferentes nem sempre é sincronizado, e a fixação de preços não é a razão para ser completamente eficaz.

Em seguida, com base no preço do contrato de entrega em diferentes momentos da mesma meta de transação, se houver um grande diferencial entre os dois preços, é possível negociar simultaneamente contratos futuros de períodos diferentes e realizar arbitragem intertemporal. Como os futuros de commodities, as moedas digitais também têm uma carteira de contratos de arbitragem intertemporal associada a elas.

Por exemplo, suponha que o spread entre a semana ETC e o trimestre ETC seja mantido em torno de 5 por um longo tempo. Se o spread atingir 7, esperamos que o spread volte a 5 em algum momento no futuro. Então você pode vender a semana ETC e comprar o trimestre ETC para reduzir o spread. vice-versa.

No 3 Embora este spread exista, muitas vezes existem muitas incertezas na arbitragem manual devido ao tempo que consome, à falta de precisão das operações manuais e aos efeitos da variação de preços.

Através do modelo quantitativo para capturar oportunidades de arbitragem e desenvolver estratégias de negociação de arbitragem, bem como algoritmos programáticos liberam automaticamente ordens de negociação para a bolsa, para capturar oportunidades de forma rápida e precisa e ganhar renda de forma eficiente, o que é o encanto da arbitragem quantitativa.

img

Este artigo irá ensiná-lo a usar a plataforma de negociação quantitativa FMZ e o contrato de futuros ETC na bolsa OkEX na negociação de moeda digital, com uma estratégia de arbitragem simples para demonstrar como capturar as oportunidades de arbitragem instantâneas e aproveitar todos os lucros visíveis, ao mesmo tempo em que cobre os riscos que podem ser encontrados.

NO.4 Criar uma estratégia de arbitragem intertemporal de moeda digital Dificuldade: nível normal Ambiente estratégico: Meta de transação: Ethereum classic (ETC) Dados de diferença: ETC semanal - ETC trimestral Período de negociação: 5 minutos Compatibilidade de posição: 1:1. Tipo de transacção: mesma variedade intertemporal Estratégia lógica: Condições de compra de posições de spread longo: se a conta corrente não tiver posições e o spread for inferior à trajectória descendente do indicador Boll, colocar uma ordem de spread, que é: comprar ETC longo semanalmente, vender ETC curto trimestralmente.

Condições de posição de venda a descoberto: se a conta corrente não tiver posições e o diferencial for superior ao valor superior do indicador de Boll, colocar uma ordem de venda a descoberto, que consiste em: vender ETC a descoberto semanalmente, comprar ETC a descoberto trimestralmente.

Fechar a condição de posição de compra de diferença longa: se a conta corrente tiver uma posição longa semanal ETC e uma posição curta trimestral ETC, e o diferencial for superior ao trilho médio do indicador Boll, realizar uma ordem de fechamento de diferença, que consiste em: vender ETC semanalmente, comprar para cobrir o ETC trimestralmente.

Fechamento da condição de posição de diferença de venda a descoberto: se a conta corrente tiver uma posição semanal curta ETC e uma posição trimestral longa ETC, e o diferencial for inferior ao trilho médio do indicador Boll, colocar uma ordem de diferença de venda a descoberto, que é: comprar para cobrir a ETC semanalmente, vender a ETC trimestralmente.

No 5 O acima é uma descrição simples de moeda digital intertemporal lógica estratégia de arbitragem, então como implementar suas próprias ideias no programa? Quadro estratégico:

img

O quadro estratégico pode ser facilmente construído de acordo com o pensamento estratégico e o processo de transacção.

  1. Preprocessamento antes da transacção.
  2. Obter e calcular dados.
  3. Faça uma encomenda e siga em frente.

NO.6 Em seguida, precisamos preencher os detalhes necessários no quadro estratégico com base no processo real de transação e detalhes da transação.

Primeiro, pré-processamento antes da transacção Passo 1: No ambiente global, declarar as variáveis globais necessárias. Declare um objeto de gráfico que configure o gráfico Diagrama Var = { } Chamar a função Chart para inicializar o gráfico Var ObjChart = Gráfico (gráfico) Declare uma matriz vazia para armazenar a sequência de espalhamento Var bar = [ ] Declarar uma variável de carimbo de tempo que regista dados históricos Var oldTime = 0 Passo 2: Configurar parâmetros externos para a estratégia.

img

Etapa 3: Definição da função de processamento de dados Função de dados básicos: Dados ()) Criar um construtor Dados e definir as suas propriedades internas, incluindo: dados de conta, dados de posição, dados de marca de data da linha K, o último preço de compra/venda do contrato de arbitragem A/B, diferença de arbitragem positiva/reversa

img

Obter a função de posição: mp ()) Verifique toda a matriz de posições, retorne o contrato especificado e o número de posições na direção especificada.

img

Função da linha K e do indicador: boll ()) Sintetize uma nova sequência de linhas K baseada nos dados do spread de arbitragem positivo/reverso e devolva os dados de rotação para cima/meio/abaixo calculados pelo indicador Boll.

img

Função de encomenda: comércio () Insira o nome do contrato da ordem e o tipo de negócio, em seguida, coloque a ordem no último preço de compra/venda e retorne o resultado após a colocação da ordem.

img

Função cancelar ordens: cancelOrders ()) Obtenha uma matriz de todas as ordens pendentes e cancele-as uma a uma, e se houver uma ordem pendente, retorne falsa, e se não houver nenhuma, retorne verdadeira.

img

Contrato único de gestão de processos: isEven ()) No caso da situação de uma única perna na negociação de arbitragem, é diretamente manipulado simplesmente fechando todas as posições.

img

Função de desenho gráfico: desenho gráfico ()) Método de chamada ObjChart.add ()) para desenhar os dados de mercado e os dados de indicadores necessários no gráfico: para cima, para baixo, para baixo, diferença de arbitragem positiva/reversa.

img

Passo 4: Na função de entrada main (), execute o código de pré-processamento antes da transação, que só é executado uma vez após o início do programa, incluindo:

Filtre as informações que não são muito importantes no console SetErrorFilter ()) Definir o tipo de moeda digital a ser negociadaexchange.IO() Esvazie os gráficos desenhados antes de iniciar o programa ObjChart.reset ()) Esvaziar as informações da barra de estado antes de iniciar o programa LogProfitReset ())

img

NO.7 Após definir o pré-processamento acima antes da transação, é necessário prosseguir para a próxima etapa, entrar no modo de votação e repetir a função onTick (). E definir o tempo de sono quando votação, porque algumas das trocas de moeda digital API tem um limite de acesso embutido para um determinado período de tempo.

img

Em segundo lugar, obter e calcular dados Passo 1: Obter o objeto de dados subjacente, o saldo da conta e os dados do indicador de boll para a lógica de negociação.

img

Terceiro, fazer uma encomenda e acompanhar Passo 1: Execute a operação de compra e venda de acordo com a lógica da estratégia acima. Primeiro, verifique se as condições do preço e do indicador são verdadeiras e, em seguida, verifique se as condições da posição são verdadeiras e, finalmente, execute a função de ordem de negociação ().

img

Passo 2: Após a encomenda, é necessário lidar com situações anormais, como encomendas pendentes e contrato único, e desenhar gráficos.

img

No. 8 Acima, criamos uma estratégia de arbitragem intertemporal de moeda digital simples através de mais de 200 linhas.

img

NO. 9 O mercado real não é tão simples, mas você pode usar este exemplo para brincar com sua imaginação.

O que precisa ser lembrado é que, com base na minha limitada experiência, a estratégia de arbitragem de período puro não vale a pena ser executada na atual situação do mercado de moeda digital, seja arbitragem triangular livre de risco ou arbitragem cross-market.

A razão é que, não importa em qual mercado de futuros de câmbio de moeda digital, a margem não é fiduciária. Quase todas as moedas digitais caíram cerca de 70% desde o início do ano. Em outras palavras, a estratégia é sempre fazer moeda, mas o preço da moeda está caindo.

O mercado de moeda digital já deixou a cadeia de blocos, assim como as tulipas, o preço sempre vem das expectativas e confiança das pessoas, e a confiança vem do preço...

Aqui para obter o código completo:

// global variable
// Declare a chart object that configures the chart
var chart = {
    __isStock: true,
    tooltip: {
        xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
    },
    title: {
        text: 'Profit and loss chart(detail)'
    },
    rangeSelector: {
        buttons: [{
            type: 'hour',
            count: 1,
            text: '1h'
        }, {
            type: 'hour',
            count: 2,
            text: '3h'
        }, {
            type: 'hour',
            count: 8,
            text: '8h'
        }, {
            type: 'all',
            text: 'All'
        }],
        selected: 0,
        inputEnabled: false
    },
    xAxis: {
        type: 'datetime'
    },
    yAxis: {
        title: {
            text: 'spread'
        },
        opposite: false,
    },
    series: [{
        name: "up",
        id: "line1,up",
        data: []
    }, {
        name: "middle",
        id: "line2,middle",
        data: []
    }, {
        name: "down",
        id: "line3,down",
        data: []
    }, {
        name: "basb",
        id: "line4,basb",
        data: []
    }, {
        name: "sabb",
        id: "line5,sabb",
        data: []
    }]
};
var ObjChart = Chart(chart); // Drawing object
var bars = []; // Store spread sequence
var oldTime = 0; // Record historical data timestamp

// Parameter
var tradeTypeA = "this_week"; // Arbitrage contract A
var tradeTypeB = "quarter"; // Arbitrage contract B
var dataLength = 10; //Length of indicator cycle
var timeCycle = 1; // The cycle of K-line
var name = "ETC"; // Currency type
var unit = 1; // Quantity of orders

// Basic data
function Data(tradeTypeA, tradeTypeB) { // input arbitrage contract A&B
    this.accountData = _C(exchange.GetAccount); // get account data
    this.positionData = _C(exchange.GetPosition); // get position data
    var recordsData = _C(exchange.GetRecords); //get k-line data
    exchange.SetContractType(tradeTypeA); // subscribe arbitrage contract A
    var depthDataA = _C(exchange.GetDepth); // deep data of arbitrage contract A
    exchange.SetContractType(tradeTypeB); // subscribe arbitrage contract B
    var depthDataB = _C(exchange.GetDepth); // deep data of arbitrage contract B
    this.time = recordsData[recordsData.length - 1].Time; // get the latest time data
    this.askA = depthDataA.Asks[0].Price; // the latest selling price of arbitrage contract A
    this.bidA = depthDataA.Bids[0].Price; // the latest buying price of arbitrage contract A
    this.askB = depthDataB.Asks[0].Price; // the latest selling price of arbitrage contract B
    this.bidB = depthDataB.Bids[0].Price; // the latest buying price of arbitrage contract B
    // Positive arbitrage spread(the latest selling price of contract A -the latest buying price of contract B )
    this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
    // Reverse arbitrage spread(the latest buying price of contract A -the latest selling price of contract B )
    this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}

// get position information
Data.prototype.mp = function (tradeType, type) {
    var positionData = this.positionData; // get position data
    for (var i = 0; i < positionData.length; i++) {
        if (positionData[i].ContractType == tradeType) {
            if (positionData[i].Type == type) {
                if (positionData[i].Amount > 0) {
                    return positionData[i].Amount;
                }
            }
        }
    }
    return false;
}

// Synthetize new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
    var self = {}; // Temporary object
    // the median of Positive arbitrage spread and reverse arbitrage spread
    self.Close = (this.basb + this.sabb) / 2;
    if (this.timeA == this.timeB) {
        self.Time = this.time;
    } // Comparing two depth data timestamps
    if (this.time - oldTime > timeCycle * 60000) {
        bars.push(self);
        oldTime = this.time;
    } // According to the specified time period, insert the spread data object in the K-line array.
    if (bars.length > num * 2) {
        bars.shift(); // Control K-line array length
    } else {
        return;
    }
    var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the Talib Library
    return {
        up: boll[0][boll[0].length - 1], // up rail of boll indicator
        middle: boll[1][boll[1].length - 1], // middle rail of boll indicator
        down: boll[2][boll[2].length - 1] // down rail of boll indicator
    } // Return a processed boll indicator data.
}

// place order
Data.prototype.trade = function (tradeType, type) {
    exchange.SetContractType(tradeType); // Resubscribe contract before placing order
    var askPrice, bidPrice;
    if (tradeType == tradeTypeA) { // if it's contract A
        askPrice = this.askA; // set askPrice
        bidPrice = this.bidA; // set bidPrice
    } else if (tradeType == tradeTypeB) { // if it's contract B
        askPrice = this.askB; // set askPrice
        bidPrice = this.bidB; // set bidPrice
    }
    switch (type) { // Match order mode
        case "buy":
            exchange.SetDirection(type); // Set order mode
            return exchange.Buy(askPrice, unit);
        case "sell":
            exchange.SetDirection(type); // Set order mode
            return exchange.Sell(bidPrice, unit);
        case "closebuy":
            exchange.SetDirection(type); // Set order mode
            return exchange.Sell(bidPrice, unit);
        case "closesell":
            exchange.SetDirection(type); // Set order mode
            return exchange.Buy(askPrice, unit);
        default:
            return false;
    }
}

// cancel order
Data.prototype.cancelOrders = function () {
    Sleep(500); // delay before canceling, because some exchanges you know...
    var orders = _C(exchange.GetOrders); // Get the array of pending orders
    if (orders.length > 0) { // if there is pending order
        for (var i = 0; i < orders.length; i++) { //check through the array of pending orders
            exchange.CancelOrder(orders[i].Id); //cancel pending orders one by one
            Sleep(500); //Delay 0.5 seconds
        }
        return false; // return false if pending orders have been cancelled
    }
    return true; //return true if there is no pending order
}

// handle holding single contract
Data.prototype.isEven = function () {
    var positionData = this.positionData; // get position data
    var type = null; // converse position direction 
    // If the length of the position array divided by some number and the remainder is 2, the result is not equal to 0 or the length of the position array is not equal to 2
    if (positionData.length % 2 != 0 || positionData.length != 2) {
        for (var i = 0; i < positionData.length; i++) { // check through the array of positions
            if (positionData[i].Type == 0) { // if it's long position
                type = 10; // Set order parameters
            } else if (positionData[i].Type == 1) { // if it's short position
                type = -10; // Set order parameters
            }
            // close all positions
            this.trade(positionData[i].ContractType, type, positionData[i].Amount);
        }
    }
}

// drawing chart
Data.prototype.drawingChart = function (boll) {
    var nowTime = new Date().getTime();
    ObjChart.add([0, [nowTime, boll.up]]);
    ObjChart.add([1, [nowTime, boll.middle]]);
    ObjChart.add([2, [nowTime, boll.down]]);
    ObjChart.add([3, [nowTime, this.basb]]);
    ObjChart.add([4, [nowTime, this.sabb]]);
    ObjChart.update(chart);
}

// trading condition
function onTick() {
    var data = new Data(tradeTypeA, tradeTypeB); // Create a base data object
    var accountStocks = data.accountData.Stocks; // account balance
    var boll = data.boll(dataLength, timeCycle); // get boll indicator data
    if (!boll) return; // return if there is no boll data
    // Spread description
    // basb = (the latest selling price of contract A - the latest buying price of contract B)
    // sabb = (the latest buying price of contract A - the latest selling price of contract B)
    if (data.sabb > boll.middle && data.sabb < boll.up) { // if sabb is higher than the middle rail
        if (data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
            data.trade(tradeTypeA, "closebuy"); // close long position of contract A
        }
        if (data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
            data.trade(tradeTypeB, "closesell"); // close short position of contract B
        }
    } else if (data.basb < boll.middle && data.basb > boll.down) { // if basb is lower than the middle rail
        if (data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
            data.trade(tradeTypeA, "closesell"); // close short position of contract A
        }
        if (data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
            data.trade(tradeTypeB, "closebuy"); // close long position of contract B
        }
    }
    if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
        if (data.basb < boll.down) { // if basb spread is lower than the down rail
            if (!data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
                data.trade(tradeTypeA, "buy"); // open long position of contract A
            }
            if (!data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
                data.trade(tradeTypeB, "sell"); // open short position of contract B
            }
        } else if (data.sabb > boll.up) { // if sabb spread is higher than the up rail
            if (!data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
                data.trade(tradeTypeA, "sell"); // open short position of contract A
            }
            if (!data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
                data.trade(tradeTypeB, "buy"); // open long position of contract B
            }
        }
    }
    data.cancelOrders(); // cancel orders
    data.drawingChart(boll); // drawing chart
    data.isEven(); // process holding single contract
}

//enter function
function main() {
    // filter the information that is not very important in the console
    SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
    exchange.IO("currency", name + '_USDT'); //Set the cryptocurrency type to be traded
    ObjChart.reset(); //Empty the drawn charts before the program starts
    LogProfitReset(); //Empty the status bar information before the program starts
    while (true) { // Enter polling mode
        onTick(); // Execute onTick function
        Sleep(500); // sleep for o.5 seconds
    }
}


Mais.

Sonhos pequenos- Muito bem!