암호화폐에 대한 상세한 고주파 거래 전략에 대한 소개

저자:발명가 양자화, 창작: 2023-03-19 19:56:11, 업데이트: 2023-09-18 19:55:58

img

저는 2020년에 고주파 거래 전략을 소개하는 기사를 썼습니다 (https://www.fmz.com/digest-topic/6228) 비록 약간의 관심을 받았지만, 그것은 매우 깊이 있지 않았다. 그 이후로 2 년 반이 흘렀고, 시장은 변했습니다. 그 기사를 발표 한 후, 내 고주파 전략은 오랫동안 안정적인 이익을 얻을 수 있었지만, 이익은 점차 감소하고 심지어 한 지점에서 멈췄습니다. 최근 몇 달 동안, 나는 그것을 리모델링하는 데 시간을 보냈고, 여전히 약간의 이익을 얻을 수 있습니다. 이 기사는 토론과 피드백의 출발점으로 봉사하는 내 고주파 거래 전략과 간단한 코드에 대한 보다 자세한 소개를 제공합니다.

고주파 거래 조건

위원회의 환불계산

예를 들어 바이낸스를 사용하여 현재 거래된 100,000 유닛마다 0.05%의 메이커 할인을 제공합니다. 일일 거래량이 1억 유닛이라면 할인액은 5,000 유닛입니다. 물론, 수령 수수료는 여전히 VIP 비율에 달려 있습니다. 따라서 전략이 주문을 받아 들일 필요가 없다면 VIP 수준은 고주파 전략에 거의 영향을 미치지 않습니다. 다양한 거래소에서 다양한 수준의 수수료 할인금이 제공됩니다. 높은 거래량을 필요로합니다. 초기에는 여전히 할인 없이도 수익을 얻을 수 있었지만 경쟁이 심화됨에 따라 할인료는 수익의 더 큰 비율을 차지했으며 고주파 거래자는 최고 비율을 추구했습니다.

속도

높은 주파수 거래는 빠른 속도 때문에 그렇게 불린다. 거래 거래소의 콜로케이션 서버에 가입하고 가장 낮은 지연 시간 및 가장 안정적인 연결을 얻는 것이 경쟁 조건 중 하나가되었습니다. 전략의 내부 처리 시간 또한 가능한 한 낮아야합니다. 이 기사는 동시 실행을 사용하는 내가 사용한 WebSocket 프레임워크를 소개합니다.

적절한 시장

높은 주파수 거래는 양적 거래의 보석으로 간주되며, 많은 알고리즘 트레이더들이 시도했다고 믿습니다. 그러나 대부분의 사람들은 돈을 벌 수 없었고 개선할 방법을 찾지 못했기 때문에 중단해야했습니다. 주된 이유는 아마도 잘못된 거래 시장을 선택했기 때문입니다. 전략의 초기 단계에서 상대적으로 쉬운 시장은 수익을 창출하고 개선에 대한 피드백을 받기 위해 거래를 목표로 삼아야하며, 이는 전략의 발전에 유리한 것입니다. 가장 치열한 경쟁 시장에서 시작하여 많은 경쟁자와 경쟁하는 경우, 아무리 노력해도 돈을 잃게 될 것이며, 빠르게 포기 할 것입니다. 나는 새로 출시 된 영구 계약 거래 쌍으로 시작하는 것이 좋습니다. 경쟁자가 적고, 특히 상대적으로 큰 거래량이있는 거래가 더 쉬워지기 때문입니다. BTC와 ETH는 거래량이 가장 높고 가장 활발하지만 생존 가능성이 가장 어렵습니다.

경쟁을 직시하라

어떤 거래의 시장도 끊임없이 변화하고 있으며, 어떤 거래 전략도 일회성 솔루션이 될 수 없습니다. 이것은 시장에 진입하는 것이 가장 똑똑하고 가장 열심히 거래하는 상인과 직접 경쟁하는 것을 의미하는 고주파 거래에서 더욱 분명합니다. 제로섬 게임 시장에서, 당신이 더 많이 벌면 다른 사람들이 덜 벌습니다. 당신이 늦게 들어가면 더 어려워지고, 이미 시장에있는 사람들은 지속적으로 개선해야하며 언제든지 제거 될 수 있습니다. 3 년 또는 4 년 전은 아마도 가장 좋은 기회였습니다. 그러나 최근 디지털 통화 시장의 전체 활동 감소로 인해 초보자가 고주파 거래를 시작하는 것은 매우 어려워졌습니다.

고주파 거래 원칙

이 또는 다른 거래소를 통해 중재 기회를 찾는 것과 다른 거래소를 통해 주문을 먹어치우며 속도 이점으로 수익을 창출하는 기회를 잡는 것과 같은 고주파 거래 전략이 여러 가지가 있습니다. 단기 트렌드에서 이익을 얻는 고주파 트렌드 거래 및 매출 거래의 양쪽에서 주문을 배치하고, 포지션을 잘 제어하고 수수료 할인으로 수익을 창출하는 마켓 메이킹과 같은 마켓 메이킹 전략이 있습니다. 내 전략은 트렌드와 시장 메이킹을 결합하여 먼저 트렌드를 식별하고 그 다음 주문을 배치하여 실행 후 즉시 판매하고 재고 포지션을 보유하지 않습니다. 아래는 전략 코드에 대한 소개입니다.

전략 건축

다음 코드는 바이낸스 영구 계약의 기본 아키텍처에 기반하고 주로 웹소켓 깊이 주문 흐름 거래 및 위치 정보를 구독합니다. 시장 데이터와 계정 정보가 별도로 구독되기 때문에 최신 정보가 얻었는지 여부를 결정하기 위해 읽기 (-1) 를 지속적으로 사용해야합니다. 여기서 EventLoop (1000) 은 직접적인 죽은 루프를 피하고 시스템 부하를 줄이기 위해 사용됩니다. EventLoop (1000) 는 1000ms의 타임아웃으로 wss 또는 동시 작업 반환이있을 때까지 블록합니다.

var datastream = null
var tickerstream = null
var update_listenKey_time = 0

function ConncetWss(){
    if (Date.now() - update_listenKey_time < 50*60*1000) {
        return
    }
    if(datastream || tickerstream){
        datastream.close()
        tickerstream.close()
    }
    // need APIKEY
    let req = HttpQuery(Base+'/fapi/v1/listenKey', {method: 'POST',data: ''}, null, 'X-MBX-APIKEY:' + APIKEY) 
    let listenKey = JSON.parse(req).listenKey
    datastream = Dial("wss://fstream.binance.com/ws/" + listenKey + '|reconnect=true', 60)
    // Symbols is the pair of symbol
    let trade_symbols_string = Symbols.toLowerCase().split(',')
    let wss_url = "wss://fstream.binance.com/stream?streams="+trade_symbols_string.join(Quote.toLowerCase()+"@aggTrade/")+Quote.toLowerCase()+"@aggTrade/"+trade_symbols_string.join(Quote.toLowerCase()+"@depth20@100ms/")+Quote.toLowerCase()+"@depth20@100ms"
    tickerstream = Dial(wss_url+"|reconnect=true", 60)
    update_listenKey_time = Date.now()
}

function ReadWss(){
    let data = datastream.read(-1)
    let ticker = tickerstream.read(-1)
    while(data){
        data = JSON.parse(data)
        if (data.e == 'ACCOUNT_UPDATE') {
            updateWsPosition(data)
        }
        if (data.e == 'ORDER_TRADE_UPDATE'){
            updateWsOrder(data)
        }        
        data = datastream.read(-1)
    }
    while(ticker){
        ticker = JSON.parse(ticker).data
        if(ticker.e == 'aggTrade'){
            updateWsTrades(ticker)
        }
        if(ticker.e == 'depthUpdate'){
            updateWsDepth(ticker)
        }
        ticker = tickerstream.read(-1)
    }
    makerOrder()
}

function main() {
    while(true){
        ConncetWss()
        ReadWss()
        worker()
        updateStatus()
        EventLoop(1000)
    }
}

전략 지표

앞서 언급했듯이, 내 고주파 전략은 먼저 구매 및 판매 거래를 실행하기 전에 트렌드를 식별해야합니다. 단기 트렌드를 판단하는 것은 주로 거래 데이터, 즉 방향, 가격, 양 및 거래 시간을 포함하는 aggTrade 가입을 기반으로합니다. 구매 및 판매 트레이드는 주로 깊이와 거래량을 참조합니다. 다음은 고려해야 할 자세한 지표입니다. 대부분은 구매 및 판매를 위해 두 그룹으로 나뉘어져 있으며 특정 시간 창 내에서 동적으로 계산됩니다. 내 전략의 시간 창은 10 초 이내에 있습니다.

  • 거래당 평균 거래량은 100ms 이내에 같은 방향, 가격 및 다른 주문의 거래의 집합입니다. 이것은 구매 및 판매 주문의 크기를 반영하고 높은 무게를 가지고 있습니다. 구매 주문의 거래량이 판매 주문보다 크다면 시장이 구매자에 의해 지배되고 있다고 가정 할 수 있습니다.
  • 오더 빈도 또는 오더 간격, 또한 거래 데이터에 기초하여, 이전 평균 거래량은 시간 개념을 고려하지 않았으며 완전히 정확하지 않습니다. 한 방향으로의 주문이 작은 평균 거래량을 가지고 있지만 빈도가 높으면 그 방향의 강도에 기여합니다. 평균 거래량 * 주문 빈도는 일정한 간격에서 전체 거래량을 나타내고 직접 비교를 위해 사용할 수 있습니다. 주문 도착 이벤트는 특정 시간 간격 내에서 전체 주문 가치가 얼마나 도달 될지 추정하는 데 사용할 수있는 포이슨 분포를 따르며 주문을 할 수있는 참조를 제공합니다.
  • 평균 스프레드, 판매 가격과 구매 가격의 차이입니다. 현재 스프레드는 대부분 하나의 틱입니다. 스프레드가 증가하면 트렌드가 있음을 나타냅니다. 평균 구매 및 판매 가격, 각각 구매 및 판매 거래의 평균 가격을 계산하고 최신 가격과 비교합니다. 최신 구매 주문 가격이 평균 구매 주문 가격보다 높다면 돌파구를 사전 판단 할 수 있습니다.

전략 논리

단기적 추세 를 판단 하는 것

let bull =  last_sell_price > avg_sell_price && last_buy_price > avg_buy_price &&
            avg_buy_amount / avg_buy_time > avg_sell_amount / avg_sell_time;
let bear =  last_sell_price < avg_sell_price && last_buy_price < avg_buy_price && 
            avg_buy_amount / avg_buy_time < avg_sell_amount / avg_sell_time;

마지막 사격 가격이 평균 사격 가격보다 높고 마지막 사격 가격이 평균 사격 가격보다 높고 구매 주문의 값이 일정한 간격에서 판매 주문의 값보다 높으면 단기 상승 시장이라고 판단됩니다. 하향 시장의 경우는 그 반대의 경우입니다.

주문 발송

function updatePrice(depth, bid_amount, ask_amount) {

    let buy_price = 0
    let sell_price = 0
    let acc_bid_amount = 0
    let acc_ask_amount = 0

    for (let i = 0; i < Math.min(depth.asks.length, depth.bids.length); i++) {
        acc_bid_amount += parseFloat(depth.bids[i][1])
        acc_ask_amount += parseFloat(depth.asks[i][1])
        if (acc_bid_amount > bid_amount  && buy_price == 0) {
            buy_price = parseFloat(depth.bids[i][0]) + tick_size
        }
        if (acc_ask_amount > ask_amount  && sell_price == 0) {
            sell_price = parseFloat(depth.asks[i][0]) - tick_size
        }
        if (buy_price > 0 && sell_price > 0) {
            break
        }
    }
    return [buy_price, sell_price]
}

여기, 필요한 양에 깊이 반복의 오래된 방법은 여전히 사용 됩니다. 1 초 이내에 10 동전 실행 될 수 있는 구매 주문을 가정하고 새로운 주문의 상황을 고려하지 않고, 판매 가격은 구매 주문이 위치 설정됩니다

10개의 동전을 넣을 수 있습니다. 특정 시간 창 크기를 스스로 설정해야 합니다.

주문량

let buy_amount = Ratio * avg_sell_amount / avg_sell_time
let sell_amount = Ratio * avg_buy_amount / avg_buy_time

이 비율은 마지막 판매 주문 양의 고정된 비율을 나타내고, 구매 주문 양은 최신 판매 주문 양의 고정된 비율로 나타냅니다. 이것은 전략이 현재 구매 및 판매 활동에 따라 주문 크기를 조정 할 수 있습니다.

주문 조건

if(bull && (sell_price-buy_price) > N * avg_diff) {
    trade('buy', buy_price, buy_amount)
}else if(position.amount < 0){
    trade('buy', buy_price, -position.amount)
}
if(bear && (sell_price-buy_price) >  N * avg_diff) {
    trade('sell', sell_price, sell_amount)
}else if(position.amount > 0){
    trade('sell', sell_price, position.amount)
}

그 중 avg_diff는 스프레드의 평균 차이이며, 주문을 하는 경우 구매 및 판매 차이가 이 값의 특정 배수보다 크고 시장이 상승할 때만 구매 주문이 배치됩니다. 짧은 포지션을 보유하면 포지션을 오랫동안 보유하지 않도록 포지션도 닫을 것입니다. 주문이 채워지는지 확인하기 위해 오직 메이커 주문이 배치 될 수 있으며 주문 반환을 기다리는 것을 피하기 위해 사용자 정의 주문 ID를 사용할 수 있습니다.

동시 건축

var tasks = []
var jobs = []

function worker(){
    let new_jobs = []
    for(let i=0; i<tasks.length; i++){
        let task = tasks[i]
        jobs.push(exchange.Go.apply(this, task.param))
    }
    _.each(jobs, function(t){
        let ret = t.wait(-1)
        if(ret === undefined){
            new_jobs.push(t)//未返回的任务下次继续等待
        }
    })
    jobs = new_jobs
    tasks = []
}

/*
tasks.push({'type':'order','param': ["IO", "api", "POST","/fapi/v1/order",
        "symbol="+symbol+Quote+"&side="+side+"&type=LIMIT&timeInForce=GTX&quantity="+
        amount+"&price="+price+"&newClientOrderId=" + UUID() +"&timestamp="+Date.now()]})
*/

모니터링 된 데이터

  • 지연: 고주파 거래 전략의 속도의 중요성이 강조되었습니다. 전략은 주문 배치, 주문 취소, 포지션 반환, 깊이, 주문 흐름, 전체 사이클 등과 같은 다양한 지연을 모니터링하고 기록해야합니다. 모든 비정상적인 지연은 신속하게 조사되어야하며 전체 전략 지연을 단축하는 방법을 찾아야합니다.
  • 거래량 비중: 통계는 거래량과 전체 거래량의 비율을 보여줍니다. 비중이 낮다면 여전히 개선할 여지가 있습니다. 피크 시간에는 전략의 비중이 전체 거래량에서 10% 이상에 도달 할 수 있습니다.
  • 종료 수익률: 통계는 전략의 효과 여부를 판단하는 가장 중요한 기준인 평균 종료 수익률을 보여줍니다.
  • 할인 비율: 통계는 전체 매출에 대한 할인 비율을 보여줍니다. 이는 전략이 할인에 의존하는 정도를 반영합니다. 다른 거래소에는 다른 할인 수준이 있으며, 수익이없는 전략은 더 높은 할인 수준으로 수익성이있을 수 있습니다. 오더 실패율: 오더는 단지 배치되고 채워지지만, 오더 배치 지연으로 인해 채워지지 않을 수 있습니다. 이 비율이 높으면 전략의 속도가 최적이 아니라는 것을 나타냅니다.
  • 주문 실행 비율: 플랫폼은 종종 주문 실행 비율에 대한 요구 사항을 가지고 있습니다. 너무 낮다면 전략이 너무 자주 주문을 취소하고 해결해야한다는 것을 나타냅니다. 평균 구매 및 판매 주문 거리: 이 데이터는 전략의 주문 배치와 시장 깊이 사이의 거리를 반영하며 대부분의 주문은 여전히 구매 및 판매 주문의 위치를 차지하고 있습니다.

다른 제안

  • 이 문서의 고주파 전략은 단일 거래소, 단일 통화 쌍 및 단일 시장 조건에 제한되어 있으며 제한된 적용 가능성을 가지고 있습니다. 대부분의 통화는 수익성이 높지 않지만 미래에 수익성이있을 수 있는 통화를 예측하는 것은 불가능하므로 여러 통화 또는 모든 통화를 거래하는 것이 기회를 놓치지 않는 것이 좋습니다. 거래소의 주파수 제한 하에서도 단일 로봇은 여러 거래 쌍을 거래 할 수 있습니다. 물론 최고의 속도를 위해 하나의 하위 계정에서 하나의 거래 쌍을 거래 할 수 있으며, 하나의 서버는 하나의 로봇에 해당하지만이 접근법은 훨씬 더 높은 비용을 초래할 것입니다.
  • 수익성을 기반으로 주문 크기와 조건을 결정합니다. 여러 통화를 거래하면 시도하는 비용이 너무 높을 수 있으므로 모니터링이 수익성이 없다는 것을 보여주면 거래 빈도를 줄이고 전략이 긍정적 인 수익률을 동적으로 감지하고 수익성을 향상시키기 위해 거래량을 점차 증가시킬 때까지 최소 거래량을 사용합니다.
  • 더 많은 정보를 얻으십시오: 높은 주파수 거래의 또 다른 특징은 더 많은 데이터를 처리하고 더 많은 정보를 사용하는 것입니다. 단일 거래소 및 통화 쌍의 모든 시장 데이터가 고려되어야하며, 영구 데이터는 다른 거래소 또는 다른 통화에서 같은 통화 쌍의 스팟 데이터 또는 데이터에도 해당 할 수 있습니다. 데이터가 많을수록 해당 이점이 커집니다. 예를 들어, 바이낸스는

관련

더 많은