기존 [시스템트레이딩] API를 이용한 자동매매(3) 프로그램은 ticker 하나를 매매하는 예제입니다. ticker 여러 개를 동시에 매매하는 예제에 대한 요청이 있어서 프로그램 업그래이드를 하였습니다.

 

기존 프로그램에서는 ticker 하나를 매매하므로 Trader() 클래스 하나만 사용하였지만 ticker 여러 개를 동시에 매매를 하기 위해서는 Trader()를 관리하는 class가 추가로 필요합니다. 이를 위하여 TraderMgr() 클래스를 추가하였습니다.

 

그리고 simultation을 위하여 사용하는 가상 exchange class를 수정하였습니다. 기존 가상거래소 class는 매매 기능만 있었으나, 특정 거래소의 현재가를 받아서 가상 매매를 하는 방식으로 수정하였습니다.

 

만약 upbit이 아닌 다른 거래소 시세를 이용하여 가상 매매를 한다면 아래 코드에서 해당하는 거래소로 변경하면 됩니다.

class DummyExchange(Exchange):
    def __init__(self, exchange_name, access, secret):
        super().__init__()
        self.type = ''
        self.name = 'dummy'
        self.holding = []
        if exchange_name == 'upbit' :
           self.exchange = MyUpbit(access, secret)

        self.seq_uuid = int(time.time())

 

여러 ticker를 동시에 매매하기 위하여 수정한 부분에 대하여 설명합니다.

 

우선 사용할 거래소를 생성합니다. 매매 로직에 대한 test를 먼저하여야 하므로 일단은 DummyExchange를 사용합니다. logic test가 끝나면 DummyExchange를 지우고 upbit 클래스를 사용하시면 됩니다.

#    upbit = MyUpbit(access, secret)
    upbit = DummyExchange('upbit', access, secret)

이 프로그램에서는 4개의 trading 변수를 사용하지만, 일반적으로 더 많은 변수를 사용합니다. 변수가 많아질수록 class에 넘겨주는 코드가 길어집니다. 그래서 tr_param라는 class를 만들었습니다. 변수가 추가될 때 마다 tr_params class에 추가하면 됩니다.

 

    # trading용 parameter 설정
    # 모든 ticker에 대하여 같은 설정 사용. 만약 ticker별로 별도 설정 값이 필요한 경우에는 ticker별로 설정 필요
    buy_perc = 0.03  # 시작가 대비 3% 오르면 매수
    sell_perc = 0.01 # 매수가 대비 1% 오르면 매도(익절)
    losscut = 0.01   # 매수가 대비 1% 내리면 losscut 매도(손절)
    seed_for_each_ticker = 10000
    
    tr_param = tr_params(buy_perc, sell_perc, losscut, seed_for_each_ticker)

trading에 사용할 ticker를 전달하는 방법은 여러가지가 있습니다. list 변수에 하나씩 넣어도 되지만, ticker가 많은 경우에는 부담이 갑니다. 따라서 별도 파일을 만들어서 원하는 ticker를 기록하도록 기능 추가하였습니다.

 

현재 거래할 ticker 명은  tr_tickers.txt 파일에 저장되어 있습니다. 

형태는 단순한 list입니다. 거래하고자하는 ticker를 추가/삭제하시면 됩니다.

 

[
	"KRW-MANA",
	"KRW-ANKR",
	"KRW-NPXS",
	"KRW-OBSR"
]

trader를 모아놓은 TraderMgr를 생성할 때 필요한 인자를 전달해주고, 매매를 위한 준비를 하는 함수인 prepare_to_start() 함수를 호출합니다. 이 함수에서는 ticker의 시작가, trading logic 등등 생성합니다.

    fname = '.\\tr_tickers.txt' 
    trader_mgr = TraderMgr(upbit, fname, tr_param)
    trader_mgr.prepare_to_start()

이번 예제에서는 REST 방식으로 10초에 한번씩 시세를 받아서 매매하는 방식으로 개발을 하였습니다.

 

        # 10초에 한번씩 최근 거래 값을 받아서 자동매매
        while(1) :
            trader_mgr.do_trading()
            time.sleep(10)

 websocket을 사용하는 경우에도 비슷한 방식으로 개발이 가능합니다.

 

새로 추가한 함수인 TraderMgr class의 do_trading()은 아래와 같습니다. trading할 ticker들의 현재 가격을 얻은 후 각 ticker별 trader에게 시세를 전달하여 매매 여부를 처리하도록 합니다. 기존 프로그램과의 차이는 main에서 특정 ticker용 trader의 do_trading() 함수를 부르는 부분이 TraderMgr class에 등록된 ticker용 trader를 찿아서 호출하는 방식으로 변경된 것입니다.

 

    # 주기적으로 call된다. 현재가를 읽어서 trading여부를 판단한다.
    def do_trading(self) :
        # trading에 사용될 tickers에 대하여 현재 가격을 받는다.
        prices = self.exchange.get_cur_price_all(self.int_tickers)
        if 'error' in prices[0]:
            print('could not get prepare_to_start::get_cur_price_all()', prices[0]['error']['message'], self.int_tickers)
            return

        if len(prices[0]) != len(self.int_tickers) :
            print("abnormal, ticker cnt is not the same ", len(prices), len(self.int_tickers))

        for ticker in self.traders :
            trader = self.traders[ticker]
            trader.do_trading(prices[0][ticker])  # 각 ticker용 trader에게 현재 시세 전달, trading 여부 처리

빠른 결과 확인을 위하여 매수 후 매수가 대비 1% 이상 오르면 익절, 매수 가격 대비 1% 이상 내리면 손절하도록 설정하였습니다.

 

    buy_perc = 0.03  # 시작가 대비 3% 오르면 매수
    sell_perc = 0.01 # 매수가 대비 1% 오르면 매도(익절)
    losscut = 0.01   # 매수가 대비 1% 내리면 losscut 매도(손절)

 

upbit 거래소 시세를 이용한 가상거래소에서 자동 매매 동작 결과입니다. 정상적으로 동작하고 있습니다. 실 거래소에서 매매는 아직 확인해보지 않았습니다. 익절 혹은 손절 후 재 매매하기 위해서는 매매 조건을 정교하게 정의하여야 합니다. 다. 자동 재매매를 위하여 매매 조건에 대하여 고민을 한 후 관련 기능도 update하도록 하겠습니다.

 

 

관련 소스코드는 아래 github에 저장되어 있습니다.

github.com/multizone-quant/system-trading-crypto-multi

반응형

설정

트랙백

댓글