흔한 데이터 분석쟁이 1명이 분석 시스템을 구축하고 있는 도중 나온 중간 결과..
시스템이 복잡해질수록 임계값 설정이 거칠어지고 있긴 한데, 이건 고쳐야 할 부분 ㅜㅜ
이미지에서 네츄럴은 무포지션 전환을 의미하는것임
[전체 기간 샷]
[분할1]
[분할2]
[분할3]
[분할4]
[분할5]
[분할6]
[분할7]
[분할8]
[분할9]
[분할10]
[분할11]
[백테스팅 code]
import pandas as pd
from datetime import timedelta
# 초기 설정
initial_balance = 1000000
balance = initial_balance
position = None
entry_price = 0
trade_log = []
fee_rate = 0.0005
imgae = 3.0
signal_window = 80 # 10분 (10개 분 단위로 확인)
# 매수 및 매도 시그널 캐싱
buy_signal = data['max_value_pred'] >= imgae
sell_signal = data['min_value_pred'] >= imgae
# 롤링 윈도우를 사용하여 10분 동안 매수/매도 시그널이 동시에 발생한 여부 계산
data['mixed_signals'] = (buy_signal.rolling(signal_window).max() > 0) & (sell_signal.rolling(signal_window).max() > 0)
# 백테스팅 시작
for i in range(len(data) - 1):
current_price = data.loc[i, "close_value"]
min_pred = data.loc[i, "min_value_pred"]
max_pred = data.loc[i, "max_value_pred"]
current_time = pd.to_datetime(data.loc[i, "Open_time"])
# 혼재된 시그널이 있는 경우 포지션 청산
if data.loc[i, 'mixed_signals']:
if position is not None:
# 현재 포지션 청산 및 무포지션 전환
profit = (current_price - entry_price) * (balance / entry_price) if position == 'buy' else (entry_price - current_price) * (balance / entry_price)
balance += profit
close_type = f"Close {position} -> Neutral"
trade_log.append({
"Time": current_time,
"Type": close_type,
"Entry Price": entry_price,
"Exit Price": current_price,
"Profit": profit,
"Fee": balance * fee_rate,
"Message": "Converted to neutral due to mixed signals"
})
position = None
entry_price = 0
print(f"[{current_time}] 포지션 청산 - {close_type}")
continue # 다음 루프로 넘어감
# 포지션 결정 및 청산/진입 로직
if position is None:
if min_pred > max_pred and min_pred >= imgae:
position = 'sell'
entry_price = current_price
fee = balance * fee_rate
balance -= fee
trade_log.append({
"Time": current_time,
"Type": "Enter Sell",
"Entry Price": entry_price,
"Fee": fee
})
print(f"[{current_time}] 매도 포지션 진입 - 가격: {entry_price}, fee: {fee:.2f}")
elif max_pred > min_pred and max_pred >= imgae:
position = 'buy'
entry_price = current_price
fee = balance * fee_rate
balance -= fee
trade_log.append({
"Time": current_time,
"Type": "Enter Buy",
"Entry Price": entry_price,
"Fee": fee
})
print(f"[{current_time}] 매수 포지션 진입 - 가격: {entry_price}, fee: {fee:.2f}")
elif position == 'buy' and min_pred > max_pred and min_pred >= imgae:
profit = (current_price - entry_price) * (balance / entry_price)
balance += profit
trade_log.append({
"Time": current_time,
"Type": "Close Buy -> Enter Sell",
"Entry Price": entry_price,
"Exit Price": current_price,
"Profit": profit,
"Fee": balance * fee_rate
})
# 새로운 매도 포지션 진입
position = 'sell'
entry_price = current_price
fee = balance * fee_rate
balance -= fee
print(f"[{current_time}] 매도 포지션으로 전환 - 가격: {entry_price}, fee: {fee:.2f}")
elif position == 'sell' and max_pred > min_pred and max_pred >= imgae:
profit = (entry_price - current_price) * (balance / entry_price)
balance += profit
trade_log.append({
"Time": current_time,
"Type": "Close Sell -> Enter Buy",
"Entry Price": entry_price,
"Exit Price": current_price,
"Profit": profit,
"Fee": balance * fee_rate
})
# 새로운 매수 포지션 진입
position = 'buy'
entry_price = current_price
fee = balance * fee_rate
balance -= fee
print(f"[{current_time}] 매수 포지션으로 전환 - 가격: {entry_price}, fee: {fee:.2f}")
# 최종 결과
final_balance = balance
total_profit = final_balance - initial_balance
print(f"초기 자산: {initial_balance}, 최종 자산: {final_balance}, 총 수익: {total_profit:.2f}")
# 백테스트 결과 출력
trade_log_df = pd.DataFrame(trade_log)
print(trade_log_df)
trade_log_df.to_csv("./trlog.csv")
==================
[결과]
초기 자산: 1000000, 최종 자산: 1476449.5344187291, 총 수익: 476449.53 Time Type Entry Price Fee \ 0 2024-07-01 00:00:00 Enter Buy 62776.01 500.000000 1 2024-07-02 03:52:00 Close Buy -> Enter Sell 62776.01 502.583185 2 2024-07-02 19:26:00 Close Sell -> Enter Buy 63131.90 510.715324 3 2024-07-03 01:01:00 Close Buy -> Enter Sell 62078.29 510.688068 4 2024-07-05 01:35:00 Close sell -> Neutral 62106.03 552.983393 .. ... ... ... ... 167 2024-10-22 14:37:00 Close buy -> Neutral 67280.00 732.944266 168 2024-10-22 16:30:00 Enter Sell 67026.20 732.944266 169 2024-10-25 18:15:00 Close sell -> Neutral 67026.20 732.166618 170 2024-10-25 21:24:00 Enter Sell 67165.10 732.166618 171 2024-10-25 23:52:00 Close sell -> Neutral 67165.10 738.224767 Exit Price Profit Message 0 NaN NaN NaN 1 63131.90 5666.369287 NaN 2 62078.29 16766.861312 NaN 3 62106.03 456.203270 NaN 4 56928.75 85101.338195 Converted to neutral due to mixed signals .. ... ... ... 167 67484.84 4449.482387 Converted to neutral due to mixed signals 168 NaN NaN NaN 169 67063.82 -822.352352 Converted to neutral due to mixed signals 170 NaN NaN NaN 171 66575.48 12848.465383 Converted to neutral due to mixed signals
알고리즘 매매로 수익권이 나오는구나 신기하네
사실 시그널 계산을 위한 여러개의 독립변수들과 각종 경험적 변수들이 앙상블로 혼합된 대규모 회귀... ㅇㅅㅇ
나도 퀀트 알고리즘 많이 돌려봤는데 추세가 있을때 좀 벌고 횡보때 다 쳐 갖다 버리고 그러는거 개선 안됨 감각적으로 흐름 따라 전략을 바꿔야 지속적인 수익이 가능한데 카오스계에서 특정하고 정형화된 계획 수립은 쉽지않다 결국 그냥 직접하는걸로 가게됨
괜히 세계 일류급 퀀트 트레이더들 수익률이 개 좆박은게 아님 자근자근 벌려면 벌 순 있는데 좀 크게 먹을라면 결국 직접해야댐 여기에 그런거 돌려놓고 신경꺼도 될만큼 부자 몇이나 될런진 몰겠다만
ㅇㅇ 맞음.. 그 부분을 개선하기 위한 고민이 있었는데.. 완전히 해결은 안 된 상태임.. 특히 횡보장일 때 시그널에 혼란이 오는데 지금은 무포지션으로 이를 틀어막고 있지만, 완벽하진 않음.. 더 긴 기간에 대해 테스트를 해 보고 그에 대한 고민이 필요함