켈리 베팅
퀀트 분석을 통해서 나온 승률과 손익비를 켈리 공식에 적용하여 최적의 비중을 잡는 베팅 방법. (승률 50% 이상일때만)
백테스팅 결과를 켈리 공식에 적용해서 비중 구하기
stats =
p = stats['Win Rate [%]']/100
q = 1 - p
b = (1 + stats['Avg. Trade [%]'] / 100)
f_optimal = (b * p - q) / b
# 0.008509040722422218
백테스팅에 적용하기
# 골든 크로스 매수 - 데드 크로스 매도
class SmaCross(Strategy):
def init(self):
price = self.data.Close
self.ma1 = self.I(SMA, price, 120)
self.ma2 = self.I(SMA, price, 180)
self.signal = self.I(lambda: np.repeat(np.nan, len(self.data.Close)), scatter=True)
self.portion = 0.00851
def next(self):
if crossover(self.ma1, self.ma2):
self.position.close()
self.buy(size=self.portion)
elif crossover(self.ma2, self.ma1):
self.position.close()
def buy(self, *args, **kwargs):
self.signal[-1] = 1 # On buy, input 1 instead of existing NaN
super().buy(*args, **kwargs)
# 005930 : 삼성전자
data = fdr.DataReader('005930')
bt = Backtest(data,
SmaCross,
cash=1000000,
commission=.002,
exclusive_orders=True)
stats = bt.run()
print(stats)
bt.plot()
전체 종목 및 다른 종목에도 적용해보기
from tqdm.notebook import tqdm
# 코스피 전 종목 주가 가져오기
kosdaq_list = fdr.StockListing('KOSDAQ')
stock_list = kosdaq_list.loc[:,['Name', 'Symbol']].values.tolist()
# 전 종목 주가를 딕셔너리에 저장
df_dict = dict()
for name, code in tqdm(stock_list):
_df = fdr.DataReader(code)
if len(_df) > 0 and 'Close' in _df.columns:
df_dict[name] = _df
# 골든 크로스 매수 - 데드 크로스 매도 전략
class SmaCross(Strategy):
def init(self):
price = self.data.Close
self.ma1 = self.I(SMA, price, 10)
self.ma2 = self.I(SMA, price, 20)
self.signal = self.I(lambda: np.repeat(np.nan, len(self.data.Close)), scatter=True)
self.portion = 0.9999
def next(self):
if crossover(self.ma1, self.ma2):
self.position.close()
self.buy(size=self.portion)
elif crossover(self.ma2, self.ma1):
self.position.close()
def buy(self, *args, **kwargs):
self.signal[-1] = 1 # On buy, input 1 instead of existing NaN
super().buy(*args, **kwargs)
# 전 종목을 전략 백테스팅 후 승률 딕셔너리를 만들어서 저장
winrate_dict = dict()
for key, value in tqdm(df_dict.items()):
data = value
bt = Backtest(data,
SmaCross,
cash=1000000,
commission=.002,
exclusive_orders=True)
stats = bt.run()
winrate_dict[key] = stats['Win Rate [%]']
# 딕셔너리를 내림차순 정렬
sorted_winrate_dict = dict(sorted(winrate_dict.items(), key=lambda item: item[1], reverse=True))
- dict.items() : 딕셔너리의 키와 값을 튜플로 묶어 리스트로 반환한다.
- 딕셔너리 value로 내림차순 정렬 :
- sorted(데이터, key, reverse) :
- 딕셔너리의 키와 값을 묶기 위해 .items()로 넣어서 sorted결과가 리스트로 반환된다. 따라서 dict()로 sorted()를 다시 감싸준다.
- key는 무엇을 기준으로 정렬할지. 딕셔너리key와 다름
- reverse는 오름차순 또는 내림차순 결정
- item=(키, 값)이 되어 lambda의 item[1]은 딕셔너리의 값을 의미
- sorted(데이터, key, reverse) :
켈리 공식 함수화
def kelly_criterion_portion(stats):
p = stats['Win Rate [%]'] / 100
b = (1 + stats['Avg. Trade [%]'] / 100)
q = (1-p)
f_optimal = (b*p-q)/b
return f_optimal
'퀀트' 카테고리의 다른 글
24. 게리 안토나치의 듀얼 모멘텀 전략 (0) | 2023.01.14 |
---|---|
23. 래리 윌리엄스의 변동성 돌파 전략 (0) | 2023.01.13 |
21. 백테스팅 기본 예제 (0) | 2023.01.10 |
20. 투자 전략을 과거 시장에 실험해보기 : 백테스트 (0) | 2023.01.09 |
19. 암호화폐 데이터 수집 및 상관관계 분석 (0) | 2023.01.09 |