첫 번째 커밋
This commit is contained in:
364
new_backtest.py
Normal file
364
new_backtest.py
Normal file
@@ -0,0 +1,364 @@
|
||||
import sys, time, random, os
|
||||
import json
|
||||
|
||||
# load strategy
|
||||
from backtesting import Backtest # short-tp error
|
||||
|
||||
# load functions
|
||||
from signal_helper import *
|
||||
|
||||
# load db
|
||||
from db import DB
|
||||
|
||||
from itertools import combinations
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from strategy import StrategyCandlePattern
|
||||
from multiprocessing import Process, freeze_support
|
||||
|
||||
import gc
|
||||
|
||||
|
||||
class Simulator:
|
||||
_db = DB()
|
||||
data = None
|
||||
|
||||
# set config
|
||||
top_cash = 0
|
||||
top_profit = 20
|
||||
top_win_rate = 60
|
||||
# best_pattern_arr = []
|
||||
|
||||
cash = float(1000)
|
||||
commission = float(.005)
|
||||
|
||||
# set strategy
|
||||
strategy = StrategyCandlePattern
|
||||
|
||||
# [0, 0.23, 0.38, 0.5, 0.61, 0.78, 0.88, 1]
|
||||
# pivonachi
|
||||
profit_arr = [0] + pivo(25)
|
||||
loss_arr = [0] + pivo(25)
|
||||
|
||||
filtered_signal_indicators = []
|
||||
|
||||
# 시그널 보조 지표
|
||||
base_indicators = [
|
||||
{'HEI': None},
|
||||
{'RSI_DIV': 14},
|
||||
{'MFI_DIV': 14},
|
||||
{'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, 1, 1]},
|
||||
{'STOCH_DIV': [14, 3, 3]},
|
||||
# {'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},
|
||||
]
|
||||
|
||||
def run(self):
|
||||
print('Started Simulating.', datetime.now())
|
||||
|
||||
zzz = True
|
||||
|
||||
for item in self._db.get_cron_list():
|
||||
# 이미 작동중인 봇이 있을 경우 제외 - 거래소 기준
|
||||
if self.is_bot_by_exchange_name(item):
|
||||
continue
|
||||
|
||||
if item['time_unit'] == 'hour':
|
||||
for t_time in ['hour6', 'hour4']: # 4시간, 6시간봉 시뮬레이팅
|
||||
self.simulrating_by_time(item, t_time)
|
||||
|
||||
self._db.update_simul_init_value(item['job'])
|
||||
return self.reboot()
|
||||
|
||||
self.simulrating_by_time(item, item['time_unit'])
|
||||
self._db.update_simul_init_value(item['job'])
|
||||
|
||||
return self.reboot()
|
||||
|
||||
if zzz:
|
||||
print('There is no list of items to run.', datetime.now())
|
||||
time.sleep(43200)
|
||||
|
||||
return self.reboot()
|
||||
|
||||
# multi Treading - item
|
||||
def simulrating_by_item(self, item, all_indicators, idx, t_time):
|
||||
start_time = self.get_this_time()
|
||||
|
||||
|
||||
print('작업 시작 : %s / 지표 수 : %s / 시간프레임 : %s' % (item['job'], idx, t_time))
|
||||
|
||||
# get top_profit and win rate from item-t_time
|
||||
top_info = self._db.select_top_date(item['job'])
|
||||
min_profit = 17
|
||||
if str(item['trade_type']) == 'double':
|
||||
min_profit = 35
|
||||
|
||||
# bt = Backtest(data, StrategyCandlePattern, cash=cash, commission=commission)
|
||||
|
||||
for indicators in list(combinations(all_indicators, idx)):
|
||||
for profit in self.profit_arr:
|
||||
for loss in self.loss_arr:
|
||||
# if str(item['trade_type']) == 'double' and loss > 0 and profit == 0: # 숏 포지션 목표가만 있을 시 에러
|
||||
# continue
|
||||
# if str(item['trade_type']) == 'double' and (loss != 0 or profit != 0):
|
||||
# continue
|
||||
|
||||
self.strategy.use_indicators = list(indicators)
|
||||
self.strategy.up_target = float(profit)
|
||||
self.strategy.down_target = float(loss)
|
||||
self.strategy.trade_type = str(item['trade_type'])
|
||||
|
||||
bt = Backtest(self.data, self.strategy, cash=self.cash, commission=self.commission)
|
||||
bt.run()
|
||||
|
||||
# 수익 및 거래 수 제한
|
||||
if bt._results['# Trades'] >= 5 and bt._results['Return [%]'] > min_profit and \
|
||||
(bt._results['Return [%]'] > self.top_profit or float(bt._results['Win Rate [%]']) >= 100):
|
||||
filename = 'chart/' + str(item['job']).replace('/', '_') + '_' + str(t_time) + '_' + str(
|
||||
time.time())
|
||||
|
||||
self._db.insert_simul_result(
|
||||
{
|
||||
'item': str(item['job']).replace('/', '_'),
|
||||
'time_type': t_time,
|
||||
'results': bt._results,
|
||||
'stop_profit': profit,
|
||||
'stop_loss': loss,
|
||||
'use_patterns': json.dumps(self.strategy.use_indicators),
|
||||
'use_pattern_cnt': len(self.strategy.use_indicators),
|
||||
'filename': filename,
|
||||
'period_cycle': item['period_cycle'],
|
||||
'trade_type': item['trade_type'],
|
||||
})
|
||||
|
||||
if bt._results['Return [%]'] > self.top_profit:
|
||||
self.top_profit = bt._results['Return [%]']
|
||||
# print('-' * 60)
|
||||
# print('트레이딩 종류 :', item['trade_type'])
|
||||
# print('시간봉 :', t_time)
|
||||
# print('지표 조합 개수 :', idx)
|
||||
# print('지표 :', self.strategy.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("파일명 :", filename)
|
||||
# print('-' * 60)
|
||||
# bt.plot()
|
||||
if bt._results['Return [%]'] > 40 and float(
|
||||
bt._results['Win Rate [%]']) >= 80: # 최상의 수익인 경우 차트 저장
|
||||
bt.plot(filename=filename, open_browser=False)
|
||||
del [[filename]]
|
||||
|
||||
if bt._results['Win Rate [%]'] >= top_win_rate:
|
||||
top_win_rate = bt._results['Win Rate [%]']
|
||||
|
||||
# best_pattern_arr.append({
|
||||
# 't_time': t_time,
|
||||
# 'indicators': indicators,
|
||||
# 'profit': profit,
|
||||
# 'loss': loss,
|
||||
# 'return': bt._results['Return [%]'],
|
||||
# 'trades': bt._results['# Trades'],
|
||||
# })
|
||||
|
||||
bt = None
|
||||
del [[bt]]
|
||||
|
||||
gc.collect()
|
||||
|
||||
e = int(time.time() - start_time)
|
||||
print('(완료) 조합 지표 개수 :', idx, t_time, '{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))
|
||||
print(datetime.now())
|
||||
|
||||
gc.collect()
|
||||
|
||||
# multi Treading - fackage
|
||||
def simulrating_by_item_fackage(self, item, t_time):
|
||||
start_time = self.get_this_time()
|
||||
top_info = self._db.select_top_date(item['job'])
|
||||
|
||||
min_profit = 7
|
||||
if str(item['trade_type']) == 'double':
|
||||
min_profit = 16
|
||||
|
||||
for indicator in self.signal_indicators:
|
||||
for profit in self.profit_arr:
|
||||
for loss in self.loss_arr:
|
||||
self.strategy.use_indicators = [indicator]
|
||||
self.strategy.up_target = float(profit)
|
||||
self.strategy.down_target = float(loss)
|
||||
self.strategy.trade_type = str(item['trade_type'])
|
||||
|
||||
bt = Backtest(self.data, self.strategy, cash=self.cash, commission=self.commission)
|
||||
bt.run()
|
||||
|
||||
# 수익 및 거래 수 제한
|
||||
if float(bt._results['Return [%]']) > min_profit and float(bt._results['# Trades']) >= 5:
|
||||
if indicator not in self.filtered_signal_indicators:
|
||||
self.filtered_signal_indicators.append(indicator)
|
||||
|
||||
bt = None
|
||||
del [[bt]]
|
||||
|
||||
e = int(time.time() - start_time)
|
||||
print('시그널 지표 필터링 완료 :', '{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))
|
||||
print('지표 총합 :', len(self.filtered_signal_indicators) + len(self.base_indicators))
|
||||
print('필터 지표 리스트', self.filtered_signal_indicators)
|
||||
|
||||
if len(self.filtered_signal_indicators) < 2:
|
||||
print(item, t_time, '- 수익 모델 조건을 만족하는 전략이 없습니다.')
|
||||
return
|
||||
|
||||
all_indicators = self.filtered_signal_indicators[::-1] + self.base_indicators
|
||||
|
||||
joined = []
|
||||
for idx in range(2, 5):
|
||||
_p = Process(target=self.simulrating_by_item, args=(item, all_indicators, idx, t_time,))
|
||||
_p.start()
|
||||
joined.append(_p)
|
||||
|
||||
# 프로세스 조인
|
||||
for _p in joined:
|
||||
_p.join()
|
||||
|
||||
|
||||
def simulrating_by_time(self, item, t_time):
|
||||
self.top_profit = 20
|
||||
self.top_win_rate = 60
|
||||
|
||||
'''
|
||||
"day": "24H",
|
||||
"hour12": "12H",
|
||||
"hour6": "06H",
|
||||
"hour": "01H",
|
||||
"minute30": "30M",
|
||||
"minute10": "10M",
|
||||
"minute5": "05M",
|
||||
"minute3": "03M",
|
||||
'''
|
||||
data = self._db.get_price_data_from_item_table(item['job'], item['period_cycle'])
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
# date = df['date'].copy()
|
||||
|
||||
# 최소 데이터 기준 일자 조건문(2달)
|
||||
std_date = datetime.now() - relativedelta(months=2)
|
||||
if df['date'][0] > std_date:
|
||||
del [[df]]
|
||||
return
|
||||
|
||||
df.set_index(df['date'], inplace=True)
|
||||
|
||||
data_columns_init(df)
|
||||
df.index.name = str(item['job']).replace('/', '_')
|
||||
|
||||
if t_time != 'hour' and t_time != 'day':
|
||||
time_type = {
|
||||
'hour': '60min',
|
||||
'hour2': '120min',
|
||||
'hour4': '240min',
|
||||
'hour6': '360min',
|
||||
'hour12': '720min',
|
||||
# 'week': 'W',
|
||||
# 'month': 'M',
|
||||
}
|
||||
ohlc_dict = {
|
||||
'Open': 'first',
|
||||
'High': 'max',
|
||||
'Low': 'min',
|
||||
'Close': 'last',
|
||||
'Volume': 'sum'
|
||||
}
|
||||
# df = df.resample(time_type[t_time], how=ohlc_dict, label='left', base=540)
|
||||
df = df.resample(time_type[t_time], label='left', base=540).agg(ohlc_dict)
|
||||
|
||||
df = df[:-1]
|
||||
|
||||
self.data = df
|
||||
self.simulrating_by_item_fackage(item, t_time)
|
||||
self.data = None
|
||||
|
||||
def get_this_time(self):
|
||||
return time.time()
|
||||
|
||||
def is_bot_by_exchange_name(self, item):
|
||||
target = item['job'].split('/')
|
||||
|
||||
return self._db.is_bot_by_exchange_name(target[1])
|
||||
|
||||
# reboot for windows
|
||||
def reboot(self):
|
||||
print('재부팅 예약 되었습니다.')
|
||||
return os.system("shutdown -t 60 -r -f")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
b = Simulator()
|
||||
b.run()
|
||||
Reference in New Issue
Block a user