블록체인 양적 투자 시리즈 과정 (3) 캘린더 스프레드 중재

저자:루비, 창작: 2018-08-27 16:49:50, 업데이트:

제1호 1987년에 소로스가 쓴 책 '금융의 대화학'에서는 중요한 제안이 있습니다. 시장 가격이 항상 잘못된 것이라는 의미에서 미래에 대한 편향적인 시각을 제시한다는 것입니다. 시장 유효성 가설은 이론적 가정에 불과하다. 사실 시장 참여자는 항상 이성적이지 않으며, 각 시점에서 참가자는 모든 정보를 완전히 습득하고 객관적으로 해석할 수 없다. 동일한 정보일지라도 모든 사람들의 피드백은 다르다.

즉, 가격 자체는 이미 시장 참여자의 잘못된 기대를 포함하고 있으므로 본질적으로 시장 가격은 항상 잘못됩니다. 이것은 중재자의 이익의 원천 일 수 있습니다.

img

제2호 위의 원칙을 바탕으로, 우리는 또한 비효율적인 선물 시장에서, 서로 다른 기간의 배달 계약의 시장 영향은 항상 동기화되지 않으며, 가격 결정은 완전히 효과적이지 않은 이유입니다.

그 다음, 같은 거래 목표의 다른 시간에 배달 계약의 가격을 기반으로 두 가격 사이에 큰 스프레드가 있다면, 다른 기간의 선물 계약을 동시에 거래하고 시간 간 중재를 수행 할 수 있습니다. 재화 선물과 마찬가지로 디지털 화폐는 또한 시간 간 중재 계약 포트폴리오가 연관되어 있습니다. 예를 들어, OkEX 거래소에서: ETC 주, ETC 다음 주, ETC 분기.

예를 들어, ETC 주간과 ETC 분기 사이의 스프레드는 오랫동안 약 5에서 유지됩니다. 스프레드가 7에 도달하면, 우리는 스프레드가 미래에 어느 시점에 5로 돌아갈 것으로 예상합니다. 그러면 ETC 주간을 판매하고 ETC 분기를 구입하여 스프레드를 단축할 수 있습니다. 그 반대.

제3호 이 스프레드가 존재하지만 수동 중재는 시간이 오래 걸리고 정확도가 떨어지고 가격 변화 효과가 있기 때문에 종종 많은 불확실성이 있습니다.

양적 모델을 통해 중재 기회를 포착하고 중재 거래 전략을 개발하며, 프로그래밍 알고리즘을 통해 거래 명령을 자동으로 거래소에 발송하여 빠르고 정확하게 기회를 포착하고 효율적으로 수익을 창출합니다. 이는 양적 중재의 매력입니다.

img

이 기사에서는 디지털 통화 거래에서 FMZ 양적 거래 플랫폼과 OkEX 거래소에서 ETC 선물 계약을 사용하는 방법을 가르쳐줍니다. 간단한 중재 전략으로 즉각적인 중재 기회를 포착하고 눈에 보이는 모든 이익을 포착하는 방법을 보여줍니다. 동시에 발생할 수있는 위험을 헤지합니다.

제4호 디지털 화폐의 시간 간 중재 전략을 만들자 난이도: 보통 수준 전략적 환경: 거래 대상: 이더리움 클래식 (ETC) 스프레드 데이터: ETC 주간 - ETC 분기 거래 기간: 5분 위치 일치 1:1 트랜잭션 유형: 같은 종류 시간 간 전략 논리: 긴 스프레드 포지션 구매 조건: 현장 계좌에 포지션이 없으며 스프레드가 볼 지표의 하향 트레일보다 작다면 스프레드 오더를 배치합니다. 즉: 주간 긴 ETC를 구매하고, 분기적으로 짧은 ETC를 판매합니다.

짧은 판매 스프레드 포지션 조건: 현재 계좌에 포지션이 없으며 스프레드가 볼 지표의 상향 레일보다 높다면 스프레드 오더를 배치합니다. 즉: 주간 ETC를 짧은 판매, 분기적으로 ETC를 긴 구매.

긴 스프레드 입장을 매입하는 조건: 매출 계좌가 주간 긴 ETC 입장을 보유하고 있고 분기 짧은 ETC 입장을 보유하고 있으며 스프레드가 볼 지표의 중간 레일보다 높다면, ETC를 주간 매각하고 분기적으로 ETC를 덮기 위해 매입하는 긴 스프레드 명령을 두십시오.

짧은 판매 스프레드 포지션 조건의 종료: 현재 계좌가 주간 ETC 짧은 포지션과 주간 ETC 긴 포지션을 보유하고 있으며 스프레드가 볼 지표의 중간 레일보다 낮다면, 밀린 스프레드 명령을 두십시오. 즉: 주간 ETC를 덮기 위해 구매하고, 주간 ETC를 판매합니다.

NO.5 위는 디지털 통화 간시적 중재 전략 논리의 간단한 설명입니다, 그렇다면 프로그램에서 자신의 아이디어를 구현하는 방법? 우리는 FMZ 양적 거래 플랫폼에서 프레임워크를 먼저 구축하려고 노력했습니다. 전략 틀:

img

전략 프레임워크는 전략적 사고와 거래 과정에 따라 쉽게 구축 될 수 있습니다. 전체 전략은 세 단계로 단순화 될 수 있습니다.

  1. 거래 전에 사전 처리.
  2. 데이터를 수집하고 계산합니다.
  3. 주문하고 따라가세요

제6호 다음으로, 우리는 실제 거래 과정과 거래 세부 사항에 기초하여 전략 프레임워크에 필요한 세부 사항을 작성해야합니다.

첫째, 거래 전에 사전 처리 단계 1: 글로벌 환경에서 필요한 글로벌 변수를 선언합니다. 차트를 구성하는 차트 객체를 선언 Var 차트 = { } 차트를 초기화하기 위해 차트 함수를 호출 Var ObjChart = 차트 (차트) 스프레드 시퀀스를 저장하기 위해 빈 배열을 선언 Var 바 = [ ] 역사 데이터를 기록하는 타임 스탬프 변수를 선언 Var oldTime = 0 단계 2: 전략의 외부 매개 변수를 구성합니다.

img

단계 3: 데이터 처리 기능을 정의 기본 데이터 기능: 데이터 ()) 생성자 데이터를 생성하고 내부 속성을 정의합니다. 계정 데이터, 위치 데이터, K-라인 데이터 타임 스탬프, 아비트레이지 계약 A/B의 최신 구매/판매 가격, 긍정적/반면적 아비트레이지 스프레드

img

위치 함수: mp () 를 얻으십시오. 위치의 전체 배열을 통해 확인, 지정된 계약과 지정된 방향으로 위치의 수를 반환. 아무 것도 없는 경우 거짓을 반환.

img

K 선과 지표 함수: boll ()) 긍정적인/반면적 대관율 스프레드의 데이터에 기초한 새로운 K-라인 염기서열을 합성합니다. 그리고 Boll 지표로 계산된 상향/중앙/하향 레일 데이터를 반환합니다.

img

주문 기능: 거래 ()) 주문 계약 이름과 거래 유형을 입력 하 고, 그 다음 마지막 구매/판매 가격에 주문을 배치 하 고 주문을 배치 한 후 결과를 반환 합니다. 주문의 두 가지 다른 방향에서 동시에 주문 할 필요가 있기 때문에, 최신 구매/판매 가격은 주문 계약 이름에 따라 함수 내에서 변환 됩니다.

img

주문 취소 함수: cancelOrders ()) 모든 미결 주문을 배열하고 하나씩 취소합니다. 미결 주문이 있다면 거짓을 반환하고, 그렇지 않으면 진실을 반환합니다.

img

프로세스 보유 단일 계약: isEven ()) 중재 거래에서 단일 다리 상황의 경우 모든 포지션을 단순히 닫아 직접 처리됩니다. 물론, 당신은 또한 추격 가격으로 변경할 수 있습니다.

img

도면 함수: 도면 ()) 그래프에 필요한 시장 데이터와 지표 데이터를 그리기 위해 ObjChart.add () 방법을 호출하십시오: 상승, 중, 하락 레일, 긍정적/반면 아비트레이지 스프레드.

img

단계 4: 입력 함수 main () 에서 트랜잭션 전에 사전 처리 코드를 실행합니다. 프로그램 시작 후 한 번만 실행됩니다.

콘솔 SetErrorFilter () 에서 매우 중요하지 않은 정보를 필터 거래할 디지털 통화 유형을 설정합니다exchange.IO()) 프로그램을 시작하기 전에 그려진 차트를 비워라 ObjChart.reset ()) 프로그램을 시작하기 전에 상태 표시줄 정보를 비어 LogProfitReset ())

img

NO.7 트랜잭션 전에 위의 사전 처리를 정의 한 후 다음 단계로 진행하고 투표 모드에 들어가 onTick () 함수를 반복해야합니다. 그리고 투표를 할 때 수면시간을 설정하세요. 왜냐하면 일부 디지털 통화 거래소 API는 특정 기간 동안의

img

둘째, 데이터를 얻고 계산합니다. 단계 1: 거래 논리를 위해 기본 데이터 객체, 계좌 잔액 및 boll 지표 데이터를 얻으십시오.

img

셋째, 주문하고 후속 조치를 취합니다. 단계 1: 위의 전략 논리에 따라 구매 및 판매 작업을 수행하십시오. 먼저 가격 및 지표 조건이 사실인지 확인하고 위치 조건이 사실인지 확인하고 마지막으로 거래 () 명령 기능을 실행하십시오.

img

단계 2: 주문을 한 후, 미뤄진 주문 및 단일 계약을 보유하는 것과 같은 비정상적인 상황을 처리하고 차트를 작성해야합니다.

img

8 위에, 우리는 200개 이상의 줄을 통해 간단한 디지털 통화 시간 간 중재 전략을 만들었습니다. 전체 코드는 다음과 같습니다.

img

NO.9 이 전략은 트리거 역할을 합니다. 실제 시장은 그렇게 간단하지는 않지만, 이 예를 이용해 상상력을 발휘할 수 있습니다.

제가 한정된 경험을 바탕으로 한 것은 현재 디지털 화폐 시장 상황에서는 순수 기간 중재 전략은 기본적으로 실행할 가치가 없다는 것입니다. 위험 없는 삼각형 중재이든 시장 간 중재이든 말이죠.

이 이유는 디지털 통화 거래소의 선물 시장에 상관없이 마진이 비정상적이지 않기 때문입니다. 거의 모든 디지털 화폐는 올해 초부터 약 70% 감소했습니다. 다른 말로, 전략은 항상 화폐를 만들고 있지만 화폐의 가격이 떨어지고 있습니다.

넓은 시각으로 보면 디지털 통화 시장은 이미 블록체인을 떠났습니다. 그 때 툴리핀과 마찬가지로, 가격은 항상 사람들의 기대와 신뢰에서 비롯되며, 신뢰는 가격에서 비롯됩니다.

여기 전체 코드를 얻으세요:

// 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
    }
}


더 많은

작은 꿈좋아!