< 3. 실 거래 후 보완된 ETF 변동성 돌파 전략 - 개별 종목 수익율 계산>


1. 개요

2. 데이터 수집


지난 포스트까지 ETF 종목에 일봉 데이터를 수집했습니다. 이번 포스트에서는 수집한 모든 일봉 데이터에 대해 변동성 돌파 전략를 적용해 각 종목들의 일별 수익율을 구하겠습니다. 


변동성 돌파 전략 매수/매도 알고리즘은 아래와 같습니다. 


매수 : ( 전일 고가 - 전일 저가 ) * Scope + 시초가 <= 현재가   [ Scope : 0.4, 0.8, 1.2 ]

* ( 전일 고가 - 전일 저가 )가 0 이상이어야 함.

매도 :  다음 날 시초가 또는 당일 종가


이전 변동성 돌파 전략 알고리즘과 달라진 것은 Scope와 매도 시점입니다. Scope 값을 이전에는 0.2 단위로 했습니다. 이는 과최적화 문제를 유도했습니다. 그래서 0.4 단위로 변경했습니다. 매도 시점은 이전에 다음 날 시초가로 오버나잇을 했지만 이번에는 오버나잇하지 않고 당일 종가에 파는 전략도 별도로 계산할 예정입니다.


아래 사진은 계산한 종목별 일별 수익율을 저장할 테이블 이름과 해당 테이블의 스키마입니다. 모든 DB의 스키마는 같습니다.



04,08,12는 Scope 값을 나타내고 over는 매도 시점이 당일 종가인지 다음날 시가인지 의미합니다. 

여기서 사용한 코드에 대한 설명은 생략합니다. 이전 포스트들에서 많이 다뤘기 때문입니다. 대신 주석을 달았습니다. 

DB.py

from sqlalchemy import create_engine import pymysql pymysql.install_as_MySQLdb() import pandas as pd class StockDB(): def __init__(self): self.engine = create_engine("mysql+mysqldb://root:" + "qhdks12#$" + "@localhost/etf1", encoding='utf-8') self.conn = pymysql.connect(host='localhost', user='root', password="qhdks12#$", db='etf1', charset='utf8') self.cursor = self.conn.cursor() # 수집한 모든 일봉 데이터를 불러온다 def select_stock(self): data = pd.read_sql('select * from etf_market order by Code, Date',self.conn, index_col='Date') return data # 당일 종가 매도한 수익율 데이터 insert def insert_profit_scope(self,data, scope): data.to_sql(name="profit_scope_"+scope, con=self.engine, if_exists='append') self.conn.commit() # 다음날 시초가 매도한 수익율 데이터 insert def insert_profit_scope_over(self,data, scope): data.to_sql(name="profit_scope_"+scope+"_over", con=self.engine, if_exists='append') self.conn.commit()


Main.py

import DB as db import pandas as pd # scope는 04, 08, 12 중 하나 # 종가 매도 시 변동성 돌파 전략 수익율 계산 def cal_profit( data, scope): scope = int(scope)/10 # (전일 고가 - 전일 저가) * Scope data['Sub'] = (data['High'] - data['Low']).shift(1) * scope # 시초가를 더해 종목의 목표 매수가 계산 data['Criteria'] = data['Sub'] + data['Open'] # 당일 고가가 목표 매수가를 넘고 (전일 고가 - 전일 저가) 가 0보다 크면 매수 data['buy'] = (data['High'] >= data['Criteria']) & (data['Sub'] > 0) data = data.dropna(axis=0) # 수익율 계산, 슬리피지 : 0.1퍼 data['Profit'] = round(data['Close'] / data['Criteria'], 4) - 0.001 # 매수하지 않은 데이터는 수익율은 1로 설정 data.loc[data['buy'] == False, 'Profit'] = 1 profit = pd.DataFrame({'Profit': data['Profit'], 'Code':data['Code']}) profit.index.name = 'Date' data= "" return profit # 다음날 시가 매도 시 변동성 돌파 전략 수익율 계산 def cal_profit_over( data, scope): scope = int(scope)/10 # (전일 고가 - 전일 저가) * Scope data['Sub'] = (data['High'] - data['Low']).shift(1) * scope # 시초가를 더해 종목의 목표 매수가 계산 data['Criteria'] = data['Sub'] + data['Open'] # 당일 고가가 목표 매수가를 넘고 (전일 고가 - 전일 저가) 가 0보다 크면 매수 data['buy'] = (data['High'] >= data['Criteria']) & (data['Sub'] > 0) # 오버나잇이기 때문에 다음날 시초가를 매도가로 설정 data['Next_Open'] = data['Open'].shift(-1) data = data.dropna(axis=0) # 수익율 계산, 슬리피지 : 0.1퍼 data['Profit'] = round(data['Next_Open'] / data['Criteria'] , 4) - 0.001 # 매수하지 않은 데이터는 1로 설정 data.loc[data['buy']==False, 'Profit'] = 1 profit = pd.DataFrame({'Profit': data['Profit'], 'Code':data['Code']}) profit.index.name = 'Date' data= "" return profit scopes = ["04","08","12"] dB = db.StockDB() data = dB.select_stock() for scope in scopes: # 당일 종가 매도 수익율 계산 result = cal_profit(data.copy(), scope) # db에 수익율 데이터 insert dB.insert_profit_scope(result, scope) # 다음날 시가 매도 수익율 계산 result = cal_profit_over(data.copy(), scope) # db에 수익율 데이터 insert dB.insert_profit_scope_over(result, scope)





참고로 필자는 컴퓨터 공학과를 재학 중인 대학생입니다. 따라서 코드가 완벽할 수 없습니다. 알고리즘이나 코드가 비효율적이거나 오류가 있다면 댓글 달아주세요..

+ Recent posts