회사 동료 분이 같이 저녁을 먹다가 이걸 왜 열심히 하냐 물어보셨다.
뭐라 답하지 조금 고민하다가 무지개를 쫓아가는 중이라 말씀드렸다.
무지개의 끝에 닿지 못할 수도 있지만, 그 끝을 따라가는 과정이 즐겁다고 했다.
봄이 오고 웃을 일도 많이 생기면서 마음도 조금 풀린거 같다.
처음에는 세상을 노려보는 마음으로 시작했다가, 지금은 다시 세상을 바라보면서 즐기고 있다.
Backtrader 라이브러리를 활용하려는데 자유도가 상당히 높아서 시작점을 어떻게 잡아야 할 지 고민을 했다.
1. 하책: 매뉴얼을 모두 정독하고 하나씩 쌓아올린다.
- 시간이 오래 걸리고, 모든 기능이 다 필요하지 않다.
- 그래도 알아두면 써먹을 데가 있다.
2. 중책: LLM한테 내 코드를 주고 다 변경해달라 한다.
- LLM은 정답을 말하지 않는다. '그럴듯한' 코드를 뱉어주기에 어차피 검증은 내가 해야한다.
- 코드 짜는데 10분. 수정하는데 1시간이 걸릴 거 같다.
3. 상책: 부분적으로 변경할 수 있는 코드를 점진적으로 변경한다.
- lean start. 맨땅에 헤딩할 때는 대부분 옳은 방식이다.
- 점진적으로 해당 라이브러리 활용도를 높여갈 수 있다.
- 코드 변경에 대한 side-effect를 조절할 수 있다.
- 생성형 AI로 컨트롤 가능하게 생산성을 높일 수 있다.
1. Skeleton 코드 작성
Docs의 Quuick start와 LLM을 참고해 간단한 코드를 작성한다.
import backtrader as bt
import pandas as pd
from datetime import datetime
from logic.get_data import GetData
class SimpleStrategy(bt.Strategy):
def __init__(self):
self.sma = bt.indicators.SimpleMovingAverage(self.data.close, period=10)
def next(self):
if not self.position:
if self.data.close[0] > self.sma[0]:
self.buy()
else:
if self.data.close[0] < self.sma[0]:
self.sell()
# 1. 데이터 로딩
code = 'A000500'
date = datetime(2024, 11, 25)
df = GetData.get_one_day_ohlcv_data(code, date)
df['timestamp'] = pd.to_datetime(df['timestamp'])
df.set_index('timestamp', inplace=True)
bt_df = df[['open', 'high', 'low', 'close', 'volume']].copy()
# 2. Backtrader용 데이터 포맷 변환
data = bt.feeds.PandasData(
dataname=bt_df,
timeframe=bt.TimeFrame.Minutes,
compression=5
)
# 3. Cerebro 엔진 설정
cerebro = bt.Cerebro()
cerebro.adddata(data)
cerebro.addstrategy(SimpleStrategy)
cerebro.run()
cerebro.plot()
2. 코드 교체
대장주 교체가 빈번했던 일자 + 교체된 대장주가 다시 대장주가 된 일자를 파악해 해당 일자를 인자로 넣어 코드 교체를 진행한다.
현재 프로세스는 아래와 같다.
1) 대장주 IN & OUT 시각 체크 -> 2) 대장주 5분봉 Dataframe 조회 -> 3) Dataframe slicing -> 4) Concat Dataframe -> 5) Run backtesitng -> 6) 매매 내역 정리 -> 7) 수익률 / 승률 계산
5를 적용하고 6, 7 가능 여부를 체크한다. 6, 7은 뭐 안 될리가 없겠지..
# Calc & print portfolio
if not top_stock_df.empty:
df = top_stock_df
df = df.sort_values(by="timestamp").reset_index(drop=True)
df.set_index("timestamp", inplace=True)
# 필요한 컬럼만 유지
df = df[['open', 'high', 'low', 'close', 'volume', 'code']]
data = bt.feeds.PandasData(
dataname=df,
timeframe=bt.TimeFrame.Minutes,
compression=5
)
cerebro = bt.Cerebro()
cerebro.addstrategy(FocusStockStrategy)
cerebro.adddata(data)
strategies = cerebro.run()
# ✅ 전략 인스턴스로부터 매매 내역 가져오기
strategy = strategies[0]
trade_df = strategy.trades_df
# 출력 (Jupyter 환경 기준)
display(trade_df)
결과는..
뭔가 잘못됐다.
아마 중간에 빵꾸난 데이터, 코드가 많을 것으로 사료된다.
뼈대는 잡았으니, 이제 디버깅을 하며 try & error 반복과 backtrader 매뉴얼을 정독해야한다.
'Quant' 카테고리의 다른 글
퀀트 전략 업데이트 (9) : Apply Backtrader (0) | 2025.04.01 |
---|---|
퀀트 전략 업데이트 (8) : Vive coding (0) | 2025.03.29 |
퀀트 전략 업데이트 (6) : Backtesting library 조사 (1) | 2025.03.24 |
퀀트 전략 업데이트 (5) : 데이터 파이프라인 업데이트 (0) | 2025.03.22 |
퀀트 전략 업데이트 (4) : Supervised learning (0) | 2025.03.19 |