준비작업 : EMA 200 곡선, Stocastic RSI, RSI
- 매수
1. ema 200 값보다 캔들이 위에 있어야 함
2. stocastic rsi가 25 미만이어야 함
3. k(파란색 선)가 d(주황색 선)보다 위에 있어야 한다(이전 캔들과 비교하여 돌파 하는 걸 캐치하면 될 것 같다.)
- 매도 :
1. 매수를 진행하고 나서 3퍼센트 이상 넘으면 매도하라고 하는데 여기서는 2 퍼센트 이상일 때 매도 한다.
2. 손절을 1퍼센트 밑으로 떨어질 때 매도
함수명은 ema 및 stocastic-rsi를 조합한 전략으로서 stocastic_rsi_ema_mix_function.py로 작성했다. 함수 네이밍 하는게 제일 시간 오래걸리는 것 같다.
defstocastic_rsi_ema_mix_funnction(data:StockData,weight:int,name:str,timeperiod:int=200,rsi_period:int=14,fastk_period=3,fastd_period=3,fastd_matype=0,buy_rate:float=25.0,sell_profit:float=2.0,sell_lose:float=-1.5):df=data.data# pandas DataFrame이며 주식 데이터 OHLCV(시가-open, 고가-high, 저가-low, 종가-close, 거래량-volume)가 들어 있다.df['ema']=talib.EMA(df['close'],timeperiod=timeperiod)df['fastk'],df['fastd']=talib.STOCHRSI(df['close'],timeperiod=rsi_period,fastk_period=fastk_period,fastd_period=fastd_period,fastd_matype=fastd_matype)# 현 Stocastic RSI를 이전 값과 비교하기 위해 추가하였다.df['before_fastk']=df['fastk'].shift(1)df['before_fastd']=df['fastd'].shift(1)def_buy_signal(r:pd.Series):# 매수조건 1 : 종가가, ema 200일 선보다 위로 올라가 있어야 한다.ifr.close>r.ema:# 매수조건 2 : buy_rate(Stocastic RSI 값)이 25 미만일 경우 진입 준비 한다.ifr.fastk<buy_rateandr.fastd<buy_rate:# 매수조건 3: r.fastk가 r.fastd 보다 위로 올라가져 있으면 매수를 한다. 또한, 이전 StocasticRSI와 비교하여 상향할경우도 추가하였다.ifr.before_fastk<r.fastkandr.before_fastd<r.fastd:ifr.fastk>r.fastd:return(StrategyResultColumnType.BUY,weight)return(StrategyResultColumnType.KEEP,0)
해당 전략을 만든 후 아래와 같이 ETH(이더리움) 2023-06-01 부터 현재까지 30분 봉 데이터를 불러와서 백테스팅을 진행해주자.
%load_extautoreload%autoreload2importpandasaspdfrombacktest.use_cases.backtest_executeimportbacktest_executefrombacktest.use_cases.strategy_executeimportstocastic_rsi_ema_mix_funnctionfrombacktest.request.stockdata_from_repoimportbuild_stock_data_from_repo_requestfrombacktest.use_cases.stockdata_from_repoimportstockdata_from_repofrombacktest.repository.webrepo.crypto.upbit_repoimportUpbitRepofrombacktest.domains.backtest_plot_packageimportBacktestPlotPackagefrombacktest.domains.backtestimportBacktestfrombacktest.domains.strategyimportStrategyfrombacktest.domains.stockdataimportStockData## 데이터를 UpbitAPI에서 가져오는 부분request=build_stock_data_from_repo_request(filters={'order__eq':'ETH','from__eq':'2023-06-01','chart_interval__eq':'30m'})response=stockdata_from_repo(UpbitRepo(),request=request,cache=True)stockdata=response.value## 전략을 세팅하는 부분, options에는 아무것도 넣지 않고 기본값으로 세팅하였다.strategy=Strategy(name='stocastic_rsi_ema_mix_funnction',function=stocastic_rsi_ema_mix_funnction,weight=1,options={})## 백테스팅을 만드는 부분backtest=Backtest(strategy_list=[strategy],stockdata_list=[stockdata])defcustom_weight_score_function(first,second,third):return((first)*2/(second+third+1))plot_package=BacktestPlotPackage()## 백테스팅을 실행하는 부분backtest_result=backtest_execute(backtest,verbose=False,save_strategy_result=True,save_raw_csv_file='example.csv',weight_score_function=custom_weight_score_function,plot_package=plot_package).value
그래프를 따로 출력한 결과, Stocastic RSI값이 실제 값과 이상하게 나오는 것을 확인하였다.
아래는 이더리움에 대한 그래프이며, bithumb사이트에 나온 Stocastic RSI 부분을 비교했을때, 실제 값과 상당히(매우) 차이가 나는 것을 확인할 수 있었다.
또한 아래의 그림에서 붉은색 원으로 표시한 부분들을 보면 100과 ,0이 이렇게 많이 나오는 것을 의미하는데, 의도한 것과 다르게 동작하는 것을 알 수 있었다.
그림 1 - bithumb 그래프와 비교
오류 Searching 후 적용
구글링을 하여, talib.STOCHRSI의 값이 이상하다는 글이 많았고 이를 좀더 거래소 웹 사이트에서 제공하는 데이터와 비슷하게 만들기 위해 여러 시행착오를 거친 내용들이 많았다.
그 중 이 링크에서 깊게 연구하신 분 덕분에 STOCHRSI 값을 어느정도 유사하게 할 수 있었다.
결론부터 설명하자면, RSI 값을 따로 구한 뒤, STOCH 모듈을 사용하면 어느정도 패턴이 일치하는 그래프가 그려진다는 것이다.
defstocastic_rsi_ema_mix_funnction(data:StockData,weight:int,name:str,timeperiod:int=200,rsi_period:int=14,fastk_period=3,fastd_period=3,fastd_matype=0,buy_rate:float=25.0,sell_profit:float=2.0,sell_lose:float=-1.5):df=data.data# pandas DataFrame이며 주식 데이터 OHLCV(시가-open, 고가-high, 저가-low, 종가-close, 거래량-volume)가 들어 있다.df['ema']=talib.EMA(df['close'],timeperiod=timeperiod)df['RSI']=talib.RSI(df['close'],timeperiod=rsi_period)df['fastk'],df['fastd']=talib.STOCH(df['RSI'],df['RSI'],df['RSI'],fastk_period=14,slowk_period=3,slowk_matype=0,slowd_period=3,slowd_matype=0)# 현 Stocastic RSI를 이전 값과 비교하기 위해 추가하였다.df['before_fastk']=df['fastk'].shift(1)df['before_fastd']=df['fastd'].shift(1)...
적용 결과는 아래와 같고, 붉은색 박스를 보면 이제 빗썸의 Stocastic RSI와 어느정도 비슷해 진것을 확인할 수 있었다.
그림 2 - bithumb 그래프와 비교2
다음은?
아쉽게도 이번 글에서는 BUY 시그널 생성 후 SELL 시그널을 찾는 구체적인 방법은 생각해보지 않았다.