Files
oh_my_bot_simulation/backtest.pyx
2025-12-06 22:28:22 +09:00

305 lines
9.3 KiB
Cython

import sys, time, random, os
# load strategy
# from strategies.indicator import StrategyIndicator
from backtesting import Backtest
# load functions
from indicator_util import get_indicators_values
from signal_helper import *
# Exchange API
import pybithumb
from itertools import combinations
from datetime import datetime
from trade.candle import CandlePatterns
import warnings
# from threading import Thread
from time import sleep
from strategy import StrategyCandlePattern
from multiprocessing import Process, freeze_support
from multiprocessing import Pool
import multiprocessing
import psutil
warnings.filterwarnings(action='ignore')
# set config
start_time = time.time()
cash = 1000
commission = .005
top_cash = 0
top_profit = 25
top_win_rate = 60
best_pattern_arr = []
# pivonachi
profit_arr = [0] + pivo(100)
loss_arr = [0] + pivo(10)
# 시그널 보조 지표
base_indicators = [
{'RSI_DIV': 14},
{'MFI_DIV': 14},
{'CMO_DIV': 9},
{'CCI_DIV': 20},
{'WILLR_DIV': 28},
{'RSI': 14},
{'BBANDS': [20, 2]},
{'BBANDS': [34, 2]},
{'CCI': 14},
{'AROON': 14},
{'SAR': [0.00252, 0.22]},
{'AROONOSC': 14},
{'BOP': 14},
{'CCI': 20},
{'MFI': 14},
{'MOM': 10},
{'MOM': 14},
{'ROC': 9},
{'ROC': 14},
{'WILLR': 14},
]
# 시그널 주도 지표(필터링될 지표)
signal_indicators = [
{'STOCH_DIV': [14, 3, 3]},
{'STOCH_DIV': [14, 1, 1]},
# {'STOCH_DIV': [20, 12, 12]},
{'STOCHRSI_DIV': [14, 14, 3]},
{'CMO_DIV': 14},
{'CCI_DIV': 14},
{'ADX_DIV': 14},
{'BOP_DIV': 0},
{'OBV_DIV': 0},
{'MOM_DIV': 10},
{'ROC_DIV': 14},
{'ROC_DIV': 9},
{'STOCH_DIV': [14, 3, 14]},
{'STOCH_DIV': [14, 3, 5]},
{'ADOSC_DIV': [3, 10]},
{'ULTOSC_DIV': [7, 14, 28]},
{'TRIX': [14, 9]},
{'STOCH': [20, 12, 12]},
{'STOCH': [14, 3, 14]},
{'STOCH': [14, 3, 5]},
{'DMI': 14},
{'DI': 21},
{'APO': [10, 20]},
{'MACD': [12, 26, 9]},
{'MACDFIX': 26},
{'MACDFIX': 9},
{'MACDFIX': 14},
{'MACDFIX': 31},
{'PPO': [12, 26, 9]},
{'STOCHF': [14, 3]},
{'STOCHRSI': [14, 14, 3]},
{'ULTOSC': [7, 14, 28]},
{'EMA': 30},
{'EMA': 55},
{'DEMA': 55},
{'DEMA': 100},
{'DEMA': 200},
{'MA': 21},
{'MA': 55},
{'MA': 100},
{'MAMA': [0.5, 0.05]},
{'T3': [100, 10]},
{'TRIMA': 30},
{'TRIMA': 50},
{'WMA': 30},
{'WMA': 20},
]
# for test
# base_indicators = [{'RSI': 14}, {'BBANDS': [34, 2]}, {'CCI': 20}, {'MFI': 14}, {'MOM': 14}]
# signal_indicators = [{'STOCH_DIV': [14, 3, 3]}, {'ROC_DIV': 14}, {'STOCH_DIV': [14, 3, 5]}]
# multi Treading - item
def simulrating_by_item(item, data, all_indicators, idx, t_time):
# def simulrating_by_item(data):
global top_profit
global top_win_rate
global start_time
global cash
global commission
for indicators in list(combinations(all_indicators, idx)):
for profit in profit_arr:
for loss in loss_arr:
StrategyCandlePattern.use_indicators = list(indicators)
StrategyCandlePattern.up_target = float(profit)
StrategyCandlePattern.down_target = float(loss)
bt = Backtest(data, StrategyCandlePattern, cash=cash, commission=commission)
bt.run()
# 수익 및 거래 수 제한
if bt._results['Return [%]'] > top_profit and bt._results['# Trades'] > 5:
print('-' * 60)
print('시간봉 :', t_time)
print('지표 조합 개수 :', idx)
print('지표 :', StrategyCandlePattern.use_indicators)
print("적용된 스탑프로핏 : %0.2f%%" % profit)
print("적용된 스탑로스 : %0.2f%%" % loss)
print("총 수익률 : %0.2f%%" % bt._results['Return [%]'])
print("최종 금액 : %0.2f" % bt._results['Equity Final [$]'])
print("거래 수 :", bt._results['# Trades'])
print("파일명 :", str(item)+'_'+str(t_time)+'_'+str(idx)+'_'+str(time.time()))
print('-' * 60)
# bt.plot(filename=str(item)+'_'+str(t_time)+'_'+str(idx)+'_'+str(time.time()))
top_profit = bt._results['Return [%]']
best_pattern_arr.append({
't_time': t_time,
'indicators': indicators,
'profit': profit,
'loss': loss,
'return': bt._results['Return [%]'],
'trades': bt._results['# Trades'],
})
del bt
e = int(time.time() - start_time)
print('(완료) 조합 지표 개수 :', idx, t_time, '{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))
print(datetime.now())
# multi Treading - fackage
def simulrating_by_item_fackage(item, data, t_time):
global top_profit
global top_win_rate
global start_time
global base_indicators
global signal_indicators
global cash
global commission
filtered_signal_indicators = []
for indicator in signal_indicators:
for profit in profit_arr:
for loss in loss_arr:
StrategyCandlePattern.use_indicators = [indicator]
StrategyCandlePattern.up_target = float(profit)
StrategyCandlePattern.down_target = float(loss)
bt = Backtest(data, StrategyCandlePattern, cash=cash, commission=commission)
bt.run()
# 수익 및 거래 수 제한
if bt._results['Return [%]'] > 15 and bt._results['# Trades'] > 5:
if indicator not in filtered_signal_indicators:
filtered_signal_indicators.append(indicator)
if bt._results['Return [%]'] > top_profit:
print('-' * 60)
print('시간봉 :', t_time)
print('지표 조합 개수 :', 1)
print('지표 :', StrategyCandlePattern.use_indicators)
print("적용된 스탑프로핏 : %0.2f%%" % profit)
print("적용된 스탑로스 : %0.2f%%" % loss)
print("총 수익률 : %0.2f%%" % bt._results['Return [%]'])
print("최종 금액 : %0.2f" % bt._results['Equity Final [$]'])
print("거래 수 :", bt._results['# Trades'])
print('-' * 60)
# bt.plot()
top_profit = bt._results['Return [%]']
best_pattern_arr.append({
't_time': t_time,
'indicators': [indicator],
'profit': profit,
'loss': loss,
'return': bt._results['Return [%]'],
'trades': bt._results['# Trades'],
})
del bt
e = int(time.time() - start_time)
print('시그널 지표 필터링 완료 :', '{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))
print('지표 총합 :', len(filtered_signal_indicators) + len(base_indicators))
print('필터 지표 리스트', filtered_signal_indicators)
all_indicators = filtered_signal_indicators[::-1] + base_indicators
joined = []
for idx in range(2, 5):
# simulrating_by_item(item, data, all_indicators, idx, t_time)
# item_thread = Thread(target=simulrating_by_item, args=(item, data, all_indicators, idx, t_time,))
# item_thread.start()
# with multiprocessing.Pool(processes=psutil.cpu_count(logical=False)) as pool:
# pool = Pool(processes=4)
# func = simulrating_by_item(item, data, all_indicators, idx, t_time)
# pool.map(func)
_p = Process(target=simulrating_by_item, args=(item, data, all_indicators, idx, t_time,))
# _p.daemon = True
_p.start()
joined.append(_p)
for _p in joined:
_p.join()
del item, data, all_indicators, idx, t_time
# multi Treading - time
def simulrating_by_time(item, t_time):
'''
"day": "24H",
"hour12": "12H",
"hour6": "06H",
"hour": "01H",
"minute30": "30M",
"minute10": "10M",
"minute5": "05M",
"minute3": "03M",
'''
df = pybithumb.get_ohlcv(item, t_time) # params : 종목, 시간
# 최근 두달 데이터 = 실질
if t_time == 'hour':
df = df[-1600:]
elif t_time == 'hour6':
df = df[-266:] # 최근 두달 데이터 = 실질
elif t_time == 'hour12':
df = df[-133:] # 최근 두달 데이터 = 실질
elif t_time == 'day':
df = df[-85:] # 최근 두달 데이터 = 실질
data_columns_init(df)
data = df
simulrating_by_item_fackage(item, data, t_time)
def start_backtest():
print('Started Simulating.')
for t_time in ['hour', 'hour6', 'hour12']:
simulrating_by_time('BTC', t_time)
break
# p = Process(target=simulrating_by_time, args=('BTC', t_time,))
# p.start()
# p.join() # sync
# thread = Thread(target=simulrating_by_time, args=('BTC', t_time,))
# thread.start()
# thread.join() # 동기
print('Ended Simulating.')
if __name__ == '__main__':
freeze_support()
start_backtest()