데이터 분석 & 엔지니어링 (FE, BE) & Quant 전략 수립 & 차트 분석 & 인프라 최적화 등 시스템 트레이딩에 필요한 기술들이 많다. 일 단위로 데이터를 제공하는 퀀트 플랫폼은 많지만, 내가 생각하는 분 단위 & 실시간 데이터를 제공하는 시스템은 없다. 시스템 규모와 시장 수요의 Trade-off로 인한 결과라 생각하고, 필요한 시스템을 직접 개발 중이다.
시스템 트레이딩에 몰입하다보니 점점 더 개선하고 추가할 기능들이 많아졌고, NFR(Non Functional Requirement)를 위한 Architect 최적화와 업데이트도 병행되어야 한다. 다른 스타트업에서는 9명 규모로 진행하던데 혼자서 하니 벅차긴 하다.
처음 생각보다 프로젝트 규모가 커지고, 남은 연차 13일도 갈아넣고 매일 퇴근하고 새벽 2시까지 해도 부족하지만 도전한거 끝까지 해보려한다. 이 프로젝트가 성공한다는 확신은 아직 없지만, 아무 것도 안하면 아무 일도 일어나지 않는 건 안다. 파이팅.
Working Days | 31 |
Total Trades | 68 |
Winning Trades | 28 |
Win Rate | 41.18% |
Total Profit | 35.11% |
기존 전략으로 31 영업일 동안 백테스팅을 한 결과이다.
매매 내역을 분석해서 승률과 수익률을 높여보고자 한다.
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
file_path = 'portfolio.csv' # 파일 경로를 지정하세요
df = pd.read_csv(file_path)
df
매매는 일 단위로 진행되며 각 column은 아래와 같다.
- code: 매매 종목 코드
- buy_price: 매수가
- buy_time :매수 시점
- sell_prie: 매도가
- sell_time: 매도 시점
- sell_reason: 매도 이유
- loss_threshold: 손절가
- profit: 수익률
- win_lose: 수익률 0 이상일 시 win, 미만일 시 lose
- date: 매매일자
1) 매수 시점 최적화 포인트가 있을까?
- 변동성이 강한 장초에 매수한 경우, 손실을 쉽게 본다거나
- 매매를 정리하려는 오후장에 매수를 해서 손실을 쉽게 볼 수도 있지 않을까?
df['buy_time'] = pd.to_datetime(df['buy_time'])
df['time_slot'] = df['buy_time'].dt.strftime('%H:%M')
df['time_slot'] = pd.to_datetime(df['time_slot'], format='%H:%M').dt.floor('10T').dt.strftime('%H:%M')
# 10분 단위로 매수 단위 분류
time_slot_avg = df.groupby('time_slot').agg(
average_profit=('profit', 'mean'), # 평균 수익률
count=('profit', 'size') # 데이터 개수
).reset_index()
# 단위별로 수익률 평균 구함
# 시각화
plt.figure(figsize=(12, 6))
# 막대 색상 설정: 양수는 붉은색, 음수는 푸른색
colors = ['red' if val > 0 else 'blue' for val in time_slot_avg['average_profit']]
# 막대그래프 생성
bars = plt.bar(
x=time_slot_avg['time_slot'],
height=time_slot_avg['average_profit'],
color=colors
)
# 데이터 라벨 추가
for index, row in time_slot_avg.iterrows():
plt.text(
x=index,
y=row['average_profit'],
s=f"{int(row['count'])}", # 데이터 개수
ha='center',
va='bottom' if row['average_profit'] > 0 else 'top',
fontsize=10,
color='black'
)
# 그래프 설정
plt.title('Average Profit by 10-Minute Time Slot', fontsize=16)
plt.xlabel('Time Slot (10-Minute Intervals)', fontsize=12)
plt.ylabel('Average Profit (%)', fontsize=12)
plt.xticks(rotation=45)
plt.grid(visible=True, linestyle='--', alpha=0.6)
plt.tight_layout()
plt.show()
10:50 ~ 11:40 사이에 매매를 피하면 수익을 극대화 하는 거 아닌가? 라고 볼 수도 있지만
데이터를 확인한 결과와 해당 수치가 평균값임을 감안했을 때 적용할 수 있는 인사이트를 얻지 못함.
2) 매수 시점의 상승률에 따라 최적화가 가능할까?
- 국장은 당일 상한가 30%이기 때문에 DoD가 너무 높은 경우, 매수 심리가 줄어들지 않을까?
# 'buy_dod'와 'profit' 컬럼만 선택
df_selected = df[['buy_dod', 'profit']].copy() # .copy()를 사용하여 경고 방지
# buy_dod의 값이 숫자형이어야 하므로, 숫자형으로 변환
df_selected.loc[:, 'buy_dod'] = pd.to_numeric(df_selected['buy_dod'], errors='coerce')
# profit이 양수이면 1, 음수이면 0으로 컬러 설정을 위한 새로운 컬럼 추가
df_selected.loc[:, 'profit_color'] = df_selected['profit'].apply(lambda x: 'red' if x > 0 else 'blue')
# 시각화
plt.figure(figsize=(10, 6))
sns.scatterplot(x='buy_dod', y='profit', data=df_selected, hue='profit_color', palette={'red': 'red', 'blue': 'blue'})
# 제목과 축 레이블 설정
plt.title('Buy DOD vs Profit', fontsize=16)
plt.xlabel('Buy DOD', fontsize=14)
plt.ylabel('Profit', fontsize=14)
# 그래프 보여주기
plt.show()
- DoD 1% 이하인 경우 or 20% 이상인 경우 -> 파란점(손실)만 존재 -> 필터링 추가
적용한 결과
Before | After | |
Working Days | 31 | 31 |
Total Trades | 68 | 68 |
Winning Trades | 28 | 29 |
Win Rate | 41.18% | 42.65% |
Total Profit | 35.11% | 38.56% |
승률이 3.45% 늘었다.
백데이터가 더 풍부하면 더 상세한 분석이 가능할 거 같다.
TODO
1. 일자별 상세 디버깅 필요 (리팩토링 이후, 일부 백테스팅 결과 다름)
- 테스트 코드 추가도 고려 필요
2. 백테스팅 속도 개선
- Compiler, JIT, GPU 사용 고려
3. Trading bot 끊김 대비, 파일에 status 저장 & 다시 읽기 기능 추가
'Quant' 카테고리의 다른 글
Refactoring: 백테스팅 속도 개선 (0) | 2025.02.11 |
---|---|
BackTesting : 디버깅 🐛 (2) | 2025.02.05 |
Parameter Optimization (0) | 2025.02.03 |
Quant : Backtesting - 재무제표 기반 (0) | 2022.04.27 |
Quant : Visualization - Seaborn (0) | 2022.04.13 |