파이썬 시스템 트레이딩

업데이트:

파이썬과 인연

내가 파이썬을 알게된 건 꽤 오래전이다. 컴퓨터공학과 학부시절 리눅스에 빠져 있을 때, 리눅스 매거진 이라는 잡지를 통해서 알게 되었다.

그때 내 눈길을 사로잡은 건 바로 이 코드

def swap(a, b):
    return b, a

엄청 흥미로웠다. 나는 이 직관성이 너무 마음에 들었다. Zen of Python 도 좋았다. 그리고 파이썬을 공부했다.

그런데 내가 파이썬을 쓸 일은 그리 많지 않았다. 우리 학교 학부과정은 C언어 위주로 되어 있었고, 사회로 나와선 Java로 개발을 했다. 파이썬은 오로지 가끔 새로운 것이 나오면 인터넷을 통해 정보를 얻고, 따라해 보고, 매년 파이콘을 참석하는 정도가 전부였다.

나에겐 지속적으로 붙잡고 있을 파이썬 프로젝트가 하나 필요했다. 때마침 서점에서 우연히 구입하게 된 책 파이썬과 리액트를 활용한 주식 자동 거래 시스템 구축1

시스템 트레이딩

사실 이 책이 아니더라도 파이썬 시스템 트레이딩은 이미 인터넷에 정보가 많이 있다. 책에서는 이것저것2 다루지만 정작 중요한건 증권사 연동과 이를 활용한 방법에 대한 부분 뿐이다.

무작정 그대로 따라해서 만들어 봤다. 잘 돌아간다. 그치만 그게 전부다.

정작 중요한 알고리즘이 빠져 있었다. 조회하고, 사고, 팔고 하는건 되는데 어떻게 하는지가 빠져 있다.

변동성 돌파전략

퀀트 투자라는게 있다. 다양한 전략을 소개해 준다. 그치만 좀 더 심플하고 명확한 하나의 조건으로 해보고 싶다. 그래서 찾다 보니 가상화폐 변동성 돌파전략3으로 구성한 샘플이 보였다.

이 전략은 아래와 같다.

  1. 가격 변동폭 계산: 투자 종목의 전일 고가(high)와 저가(low)의 차이(변동폭)를 계산
  2. 매수 기준: 당일 시간에서 (변동폭 * 0.5) 이상 상승하면 해당 가격에 바로 매수
  3. 매도 기준: 당일 종가에 매도

여기에 조금 보완하면 상승장 판단 여부를 붙이는 것이다. 상승장이라는게 어차피 과거를 기반으로 하는 수치이고 이것이 미래를 100% 예측할 순 없다. 사실 주식이라는게 어차피 과거 기반 데이터의 미래 예측이 아니던가.

상승장은 판단 기준은 이동평균선4 위에 있으면 상승장이라고 보는 것이다.

프로젝트 시작

주식판

그래서 만들어 봤다. 모의투자를 대상으로 했다.

class DumbPlayer(Player):
  def __init__(self, agent):
    self.name = 'dumb'
    self.ebest = agent

  def scenario(self):
    deposit = self.get_balance()
    self._decide_sell()
    self._decide_buy(deposit)

if __name__ == '__main__':
    ebest = EBest(StageType.DEMO)
    try:
        ebest.login()
        player = DumbPlayer(ebest)
        player.scenario()
    finally:
        ebest.logout()

매수/매도가 일어나는걸 보니 신기하다. 그치만 답답한게 몇 가지가 있다.

  1. 주식은 정해진 시간에만 오픈한다.
  2. 윈도우 개발환경만 지원한다.
  3. 증권사별 스펙이 너무 복잡하다.

재미는 있었지만 한정된 환경에 너무나도 오래된 레거시 API를 가지고 논다는게 답답했다. 무엇보다 정해진 장 시간에만 테스트 해볼 수 있다는 것도 불편한 부분.

코인판

그래서 환경을 코인판으로 바꿨다. REST API도 지원하고 24시간 계속 돌려볼 수 있었다. 이미 만들어둔 코드 베이스가 있어서 금방 구축했다.

# Initialize environment
context.stage = stage
context.mode = stage.mode

ScenarioStore.start()
log.info(f"STAGE: {stage.text}, MODE: {stage.mode.text}, VER: {__version__}")

# Start Nob threads
# Nob: crypto trader has own lifecycle
for crypto in NobType.DANTA.cryptos:
    nob = DantaNob(crypto, stage)
    nob.daemon = True
    nob.start()
    nob.join()
    time.sleep(1)
for crypto in NobType.SCORE.cryptos:
    nob = ScoreNob(crypto, stage)
    nob.daemon = True
    nob.start()
    nob.join()
    time.sleep(1)

# Start reporter thread
reporter = TelegramReporter()
reporter.daemon = True
reporter.start()
reporter.join()

# Start Telegram
# Should be last because of polling idle
context.bot = TelegramBot()
context.bot.start()

몇 가지 주요 개선점을 추가했다.

  1. 변동성 돌파전략의 고정 시점 매도를 개선하여 하락장을 인지하면 즉시 매도
  2. 스코어링을 기반으로 트레이딩을 하는 새로운 전략을 추가
  3. 텔레그램을 통한 현황/매수/매도/청산 등의 다양한 인터랙션 기능 추가
  4. 기간별 리포팅을 생성

시뮬레이션을 몇 주 거친 뒤 실전으로 들어갔다. 실전이 재미있지 않은가. 테스트용 푼돈이다. 내 돈을 가지고 이 녀석이 밤사이 사고팔고 하니까 재미있다.

현재까지 계속 진행 중인 프로젝트이다. 코드도 무천 많이 개선했다. 가상화폐는 훌륭한 테스트 베드이다. 언젠간 다시 주식판으로도 들어갈 코드들이다.

오픈소스?

오픈소스로 만들까 고민해 봤다. 아직은 Github 사설 저장소를 사용한다.

이유는… 아직 내놓기는 부끄럽기 때문이다. 수익률도 엉망이고. 뭔가 좀 재미를 보면 언젠가는 오픈하는걸 고민해 봐야겠다.

앞으로

파이썬은 재미있다. 밥벌이가 아닌 프로그래밍을 몇 년 만에 하는지 모르겠다. 수익률은 꽝이다. 시스템 트레이딩으로선 실패에 가깝다. 현재까지는…

그치만 앞으로 계속 함께할 수 있는 친구가 생긴 느낌이다. 수익률은 올리면 되지 뭐.

각주

  1. http://www.yes24.com/Product/Goods/87579013 

  2. 이런 종류의 책이 그렇듯이 REST, 크롤링, 웹페이지, DB 등 맛보기만 다양하게 다루면서 책의 분량만 채워놨다. 

  3. https://wikidocs.net/21888 

  4. 이동평균선, moving average, 특정 기간의 가격의 시계열 평균값 

댓글남기기