디지털 통화 고주파 전략 상세 소개

저자:리디아, 창작: 2023-03-27 16:46:14, 업데이트: 2023-09-18 20:12:59

img

디지털 통화 고주파 전략 상세 소개

저는 2020년에 고주파 전략들을 소개하는 기사를 썼습니다.https://www.fmz.com/bbs-topic/9750. 비록 꽤 많은 관심을 받았지만, 그것은 매우 깊이 있는 것이 아니었습니다. 그 이후로 2 년 이상이 흘렀고, 시장은 변했습니다. 그 기사가 출판 된 후, 내 고주파 전략은 오랫동안 안정적으로 이익을 얻을 수 있었지만, 점차적으로 이익이 감소하고 심지어 한 지점에서 멈췄습니다. 최근 몇 달 동안 나는 그것을 개편하기 위해 약간의 노력을 기울였으며, 지금은 여전히 약간의 이익을 얻을 수 있습니다. 이 기사에서, 나는 토론의 시작점으로 내 고주파 전략 아이디어와 간단한 코드를 좀 더 상세하게 소개 할 것입니다. 그리고 피드백은 환영합니다.

고주파 거래 조건

  • 리베이트 계정은 바이낸스를 예로 들자면 현재 0.0005%의 메이커 리베이트를 가지고 있다. 일일 거래 금액이 1억 U인 경우 리베이트는 5000 U이 될 것이다. 물론, 타커 수수료는 여전히 VIP 요금을 기준으로 하고 있기 때문에 전략에 타커가 필요하지 않다면, VIP 수준은 고주파 전략에 거의 영향을 미치지 않는다. 서로 다른 수준의 거래소는 일반적으로 다른 리베이트율을 가지고 있으며 높은 거래 금액을 유지해야 한다. 일부 통화 시장이 크게 변동하는 초기에는 리베이트 없이도 이익이 있었다. 경쟁이 심화됨에 따라 리베이트는 이익의 더 큰 비율을 차지하거나 심지어 그것에만 의존했다; 고주파 트레이더들은 최고 수준의 수수료를 추구했다.

  • 속도. 고주파 전략이 고주파라고 불리는 이유는 매우 빠르기 때문입니다. 교환의 컬로 서버에 가입하여 가장 낮은 지연시간과 가장 안정적인 연결을 얻는 것도 내부 경쟁의 조건 중 하나가되었습니다. 전략의 내부 소비 시간은 가능한 한 작아야하며이 기사는 동시 실행을 채택하는 내가 사용하는 웹소켓 프레임워크를 소개합니다.

  • 적절한 시장. 높은 주파수 거래는 양적 거래의 진주로 알려져 있으며 많은 프로그래밍 트레이더들이 시도했지만 대부분의 사람들은 수익을 창출하고 개선 방향을 찾지 못하기 때문에 중단했습니다. 주된 이유는 그들이 잘못된 거래 시장을 선택했기 때문입니다. 전략 개발의 초기 단계에서 상대적으로 쉬운 시장은 수익을 창출하기 위해 거래에서 수익을 창출하기 위해 선택되어야하여 수익과 개선에 대한 피드백이 있기 때문에 전략의 발전에 유도합니다. 많은 잠재적 인 상대와 가장 경쟁력있는 시장에서 경쟁하기 시작하면 아무리 노력해도 곧 돈을 잃고 포기 할 것입니다. 경쟁자가 많지 않을 때, 특히 상대적으로 큰 거래 금액이있는 경우 새 영구 계약 거래 쌍을 추천합니다. 이 때 수익이 가장 쉽습니다. BTC와 ETH는 거래액이 가장 많고 생존하기 가장 어렵습니다.

  • 경쟁에 직면. 어떤 거래의 시장은 끊임없이 변화하고 있으며, 특히 고주파 거래에서 어떤 거래 전략도 영원히 지속될 수 없습니다. 이 시장에 진입하는 것은 가장 똑똑하고 가장 열심히 거래하는 거래자들과 직접 경쟁하는 것을 의미합니다. 제로섬 게임 시장에서, 당신이 더 많이 벌면 다른 사람들이 더 적게 벌 것입니다. 당신이 더 늦게 들어가면 어려움이 더 높습니다. 이미 시장에있는 사람들도 지속적으로 개선해야합니다. 3-4 년 전은 아마도 가장 좋은 기회였습니다. 최근에는 디지털 통화 시장의 전반적인 활동이 감소하여 신입업자가 지금 고주파 거래를 시작하는 것이 매우 어렵습니다.

고주파 원리

다양한 고주파 전략이 있습니다.

  • 고주파 헤지, 이 거래소나 다른 거래소를 통해 헤지 기회를 찾아서 주문을 잡고 수익을 창출하기 위해 속도 우위에 의존합니다.
  • 고주파 트렌드, 단기 트렌드를 판단하여 수익을 창출합니다.
  • 마켓 메이커, 구매와 판매 양쪽에서 주문을 배치하고, 포지션을 잘 통제하고 할인으로 수익을 창출합니다.
  • 제가 하나씩 언급하지 않을 다른 많은 것들이 있습니다. 내 전략은 트렌드와 시장 메이커의 조합입니다. 먼저 트렌드를 판단하고 주문을 합니다. 거래가 완료되면 인벤토리 포지션을 보유하지 않고 즉시 판매 주문을 합니다. 다음으로 전략 코드와 함께 소개합니다.

전략 틀

다음 코드는 바이낸스 영구 계약의 기본 프레임워크를 기반으로 주로 웹소켓 깊이, 깊이 주문 흐름 거래 시장 데이터 및 위치 정보를 구독합니다. 시장 데이터와 계정 정보가 별도로 구독되기 때문에 최신 정보가 얻었는지 여부를 결정하기 위해 지속적으로 읽기 (read) 을 사용해야합니다. 여기서 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 are the set trading pairs
    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 내에서 동일한 방향과 가격을 가진 다른 주문의 집합입니다. 이 데이터는 높은 무게를 가지고 있으며, 구매 주문의 양이 판매 주문보다 크면 이것은 구매자가 지배하는 시장이라고 가정 할 수 있습니다.
  • 주문 주파수 또는 주문 간격, 또한 거래별 데이터에 기반하고 있으며, 앞서 언급한 평균 거래 금액은 시간의 개념을 고려하지 않으며 완전히 정확하지 않습니다. 한 방향으로의 주문이 평균 거래 금액이 작지만 빈도가 높다면 여전히 그 방향의 강도에 기여합니다. 평균 거래 금액 * 주문 주파수는 일정한 간격에서 전체 거래 금액을 나타내고 직접 비교를 위해 사용할 수 있습니다. 주문의 도착은 특정 시간 간격 내에서 도착하는 전체 주문의 금액이 얼마나 되는지 단순히 추정하고 주문 포지션을 배치하는 데 참조를 제공하는 데 사용할 수있는 포이슨 분포를 따릅니다.
  • 평균 스프레드는 비교적 쉽게 이해할 수 있습니다. 즉, 1을 판매하고 1을 구매합니다. 현재 시장은 대부분 1 틱 스프레드를 가지고 있습니다. 스프레드가 커지면 종종 시장 추세가 있음을 의미합니다.
  • 평균 구매 및 판매 가격, 각 거래의 평균 가격을 개별적으로 계산하고 최신 가격과 비교하십시오. 최근 구매 주문 가격이 평균 구매 주문 가격보다 높다면 돌파구가 발생했다고 사전 판단 할 수 있습니다.

전략 논리

단기 동향을 결정

//bull represents short-term bullish, bear represents short-term bearish
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)//Unreturned tasks will continue to wait next time
        }
    })
    jobs = new_jobs
    tasks = []
}

/*
Write the required task parameters in param
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% 이상을 차지할 수 있습니다.
  • 포지션 종료 수익률, 평균 포지션 종료 수익률을 계산하는 것은 전략의 효과 여부를 판단하는 가장 중요한 기준입니다.
  • 할인 비율, 전체 매출의 할인 비율은 전략의 할인 의존도를 반영합니다. 거래소 플랫폼은 다른 할인 수준을 가지고 있으며 수익성이없는 전략은 더 높은 할인 수준으로 수익성이있을 수 있습니다.
  • 오더 실패율은 오더를 배치하는 것만으로 거래됩니다. 오더를 배치하는 데 지연이 있기 때문에 배치되지 않을 수 있습니다. 이 비율이 높으면 전략의 속도가 유리하지 않다는 것을 의미합니다.
  • 완료 된 주문의 비율, 플랫폼은 종종 거래율에 대한 요구 사항을 가지고 있습니다. 너무 낮다면 전략이 너무 자주 주문을 취소하고 해결해야합니다.
  • 평균 구매 및 판매 주문 거리, 주문을 배치하는 전략과 시장 사이의 격차를 반영, 우리는 그들 대부분은 여전히 하나를 구입하고 판매하는 위치를 차지하는 것을 볼 수 있습니다.

다른 제안

  • 이 문서의 높은 주파수 전략은 단일 거래소, 단일 통화 및 단일 시장을 의미합니다. 그것은 큰 한계를 가지고 있으며 대부분의 상황과 통화가 수익을 창출 할 수 없습니다. 그러나 어떤 통화가 미래에 수익성이있을지 예측하는 것은 불가능하므로 기회를 놓치지 않고 여러 개 또는 모든 통화를 거래 할 수 있습니다. 교환의 주파수 제한 하에서도 로봇은 여러 거래 쌍을 거래 할 수 있습니다. 물론 최적의 속도를 위해 한 하위 계정에서 한 로봇에 해당하는 한 서버와 하나의 거래 쌍을 거래 할 수 있습니다. 그러나 이것은 훨씬 더 높은 비용을 초래할 것입니다.
  • 수익률에 따라 주문 양과 주문 조건을 결정합니다. 여러 화폐와 거래하면 높은 시도 비용이 발생합니다. 모니터링이 수익성이 없다면 최소 거래 금액을 사용하여 전략이 긍정적 인 수익률을 동적으로 모니터링 할 때까지 거래 주파수를 줄이고 점진적으로 수익률을 향상시키기 위해 거래 금액을 증가시킵니다.
  • 더 많은 정보를 얻으십시오. 고주파 거래의 또 다른 특징은 더 많은 양의 데이터를 처리하고 더 많은 정보를 사용하는 것입니다. 단일 거래소 내 단일 거래 쌍의 모든 시장 정보가 참조되어야하며, 영구 계약은 또한 같은 거래 쌍의 다른 거래소에서 얻은 데이터뿐만 아니라 다른 통화에서 얻은 데이터도 참조 할 수 있습니다. 데이터가 많을수록 해당 장점이 커집니다. 예를 들어, 바이낸스는 심볼에 의해 최고의 대기 주문 정보를 가입 할 수 있습니다. 왜냐하면 깊이와 주문 흐름의 가장 짧은 푸시 타임은 100ms이기 때문입니다. 오직 이것은 실시간이며 고주파 전략에 매우 가치 있습니다.
  • 바이낸스의 서버는 도쿄에 있습니다. 다른 거래소의 서버는 다릅니다. 자세한 내용은 거래소의 기술 직원에게 문의할 수 있습니다.
  • 이 문서의 전략 코드는 많은 번거로운 그러나 필요한 세부 사항이 제거 된 단순화된 예제 코드입니다. 사용 된 지표는 참조를 위해만 사용되며 직접 사용해서는 안됩니다. 고주파 전략 실행 시 많은 세부 사항에주의를 기울여야하며 수정 및 개선에 인내심이 필요합니다.

관련

더 많은