def main(): parser = argparse.ArgumentParser() parser.add_argument("action", choices=["backtest", "trade"]) args = parser.parse_args() if args.action == "backtest": backtest.backtest() if args.action == "trade": trade.trade()
def sf_test_multiple_pools(factor=None, sf_obj=single_factor_strategy(), *, direction='+', bb_obj=None, discard_factor=(), folder_names=None, holding_freq='w', benchmarks=None, stock_pools=('all', 'hs300', 'zz500', 'zz800'), bkt_start=None, bkt_end=None, select_method=0, do_bb_pure_factor=False, do_pa=False, do_active_pa=False, do_data_description=False, do_factor_corr_test=False, loc=-1): # 打印当前测试的策略名称 print('Name Of Strategy Under Test: {0}\n'.format(sf_obj.__class__.__name__)) cp_adj = data.read_data('ClosePrice_adj') temp_position = position(cp_adj) # 先要初始化bkt对象 bkt_obj = backtest(temp_position, bkt_start=bkt_start, bkt_end=bkt_end, buy_cost=0.0015, sell_cost=0.0015, bkt_stock_data=['ClosePrice_adj', 'ClosePrice_adj']) # 建立bb对象,否则之后每次循环都要建立一次新的bb对象 if bb_obj is None: bb_obj = barra_base() # 外部传入的bb对象,要检测其股票池是否为all,如果不是all,则输出警告,因为可能丢失了数据 elif bb_obj.bb_data.stock_pool != 'all': print('The stockpool of the barra_base obj from outside is NOT "all", be aware of possibile' 'data loss due to this situation!\n') # 根据股票池进行循环 for cursor, stock_pool in enumerate(stock_pools): # 进行当前股票池下的单因子测试 # 注意bb obj进行了一份深拷贝,这是因为在业绩归因的计算中,会根据不同的股票池丢弃数据,导致数据不全,因此不能传引用 # 对bkt obj做了同样的处理,尽管这里并不是必要的 sf_obj.single_factor_test(factor=factor, loc=loc, direction=direction, bkt_obj=copy.deepcopy(bkt_obj), base_obj=copy.deepcopy(bb_obj), discard_factor=discard_factor, folder_name=folder_names[cursor], bkt_start=bkt_start, bkt_end=bkt_end, holding_freq=holding_freq, benchmark=benchmarks[cursor], stock_pool=stock_pool, select_method=select_method, do_base_pure_factor=do_bb_pure_factor, do_pa=do_pa, do_active_pa=do_active_pa, do_data_description=do_data_description, do_factor_corr_test=do_factor_corr_test)
def backtest(self, config): results = [] all_daily_returns = [] all_objectives = [] for splits in self: start, end = splits["train"]["start_idx"], splits["train"][ "end_idx"] self.update_config( config, splits["train"]) # Update n_days and start/end date fills, stats, did_finish = backtest(config, self.ticks[start:end]) _, _, result_ = analyze_backtest(fills, stats, self.bc) results.append(result_) all_daily_returns.append( result_["returns_daily" + "_obj"]) # stats is more accurate than fills all_objectives.append(result_[self.bc["metric"] + "_obj"]) result = {} for k in results[0]: try: result[k] = np.mean([r[k] for r in results]) except: result[k] = results[0][k] # Geometrical mean is often used to average returns result["daily_gains_gmean"] = np.exp( np.mean(np.log(np.array(all_daily_returns) + 1))) result["objective_gmean"] = np.exp( np.mean(np.log(np.array(all_objectives) + 1))) - 1 return result
def backtest_single_wrap(config_: dict): config = config_.copy() exchange_name = config['exchange'] + ('_spot' if config['market_type'] == 'spot' else '') cache_filepath = f"backtests/{exchange_name}/{config['symbol']}/caches/" ticks_filepath = cache_filepath + f"{config['start_date']}_{config['end_date']}_ticks_cache.npy" mss = json.load(open(cache_filepath + 'market_specific_settings.json')) ticks = np.load(ticks_filepath) config.update(mss) try: fills, stats = backtest(config, ticks) fdf, sdf, analysis = analyze_fills(fills, stats, config) pa_closeness_long = analysis['pa_closeness_mean_long'] pa_closeness_shrt = analysis['pa_closeness_mean_shrt'] adg = analysis['average_daily_gain'] print(f"backtested {config['symbol']: <12} pa closeness long {pa_closeness_long:.6f} " f"pa closeness shrt {pa_closeness_shrt:.6f} adg {adg:.6f}") except Exception as e: print(f'error with {config["symbol"]} {e}') print('config') traceback.print_exc() adg = 0.0 pa_closeness_long = pa_closeness_shrt = 100.0 with open(make_get_filepath('tmp/harmony_search_errors.txt'), 'a') as f: f.write(json.dumps([time(), 'error', str(e), denumpyize(config)]) + '\n') return (pa_closeness_long, pa_closeness_shrt, adg)
def wrap_backtest(config, ticks): results = [] for ticks_slice in iter_slices(ticks, 0.4, 4): fills, _, did_finish = backtest(config, ticks_slice) result_ = prepare_result(fills, ticks_slice, config['do_long'], config['do_shrt']) results.append(result_) result = {} for k in results[0]: try: result[k] = np.mean([r[k] for r in results]) except: result[k] = results[0][k] # fills, _, did_finish = backtest(config, ticks) # result = prepare_result(fills, ticks, config['do_long'], config['do_shrt']) objective = objective_function(result, config['minimum_liquidation_distance'], config['max_hrs_no_fills'], config['max_hrs_no_fills_same_side']) tune.report( objective=objective, daily_gain=result['average_daily_gain'], closest_liquidation=result['closest_liq'], max_hrs_no_fills=result['max_hrs_no_fills'], max_hrs_no_fills_same_side=result['max_hrs_no_fills_same_side'])
def wrap_backtest(config, ticks): fills, _, did_finish = backtest(config, ticks) result = prepare_result(fills, ticks, config['do_long'], config['do_shrt']) objective = objective_function(result, config['minimum_liquidation_distance'], config['max_n_hours_between_fills']) tune.report(objective=objective, daily_gain=result['average_daily_gain'], closest_liquidation=result['closest_liq'], max_hours_between_fills=result['max_n_hours_between_fills'])
def main(): #general init done on config import #train weights weights = {} if cfg.train: msg('beginning to train', '+') weights = train() msg('done training', '+') #backtest algorithm if cfg.backtest: msg('beginning backtest', '+') start = time.time() backtest(weights) msg('finished testing in %s' % round(time.time() - start, 3), '+') cfg.api.account_info(cfg.today)
def daily_test(feature,dts,index,initMoney,startDt,modelFile,strategy): idx = dts>=startDt; fea = feature[idx]; cls = pickle.load(open(modelFile)); #pred = np.squeeze(cls.predict_proba(fea)[:,cls.classes_==1]); pred = np.squeeze(cls.predict(fea)); index = index[idx]; dfDec = pd.DataFrame(pred, index=pd.MultiIndex.from_tuples(index, names=['secID','tradeDate']), columns = ['DecFactor'] ); dfDec = utils_common.shiftDtPost(dfDec); dfDec.reset_index(inplace=True); dfDec.sort_values(['tradeDate','DecFactor'],inplace=True,ascending=False); decFactor = utils_common.groupDt(dfDec); backtest.backtest(initMoney,startDt,'2019-01-01',strategy,decFactor); pass;
def daily_test(feature, dts, index, initMoney, startDt, modelFile, strategy): idx = dts >= startDt fea = feature[idx] cls = pickle.load(open(modelFile)) #pred = np.squeeze(cls.predict_proba(fea)[:,cls.classes_==1]); pred = np.squeeze(cls.predict(fea)) index = index[idx] dfDec = pd.DataFrame(pred, index=pd.MultiIndex.from_tuples( index, names=['secID', 'tradeDate']), columns=['DecFactor']) dfDec = utils_common.shiftDtPost(dfDec) dfDec.reset_index(inplace=True) dfDec.sort_values(['tradeDate', 'DecFactor'], inplace=True, ascending=False) decFactor = utils_common.groupDt(dfDec) backtest.backtest(initMoney, startDt, '2019-01-01', strategy, decFactor) pass
def single_sliding_window_run(config, data, do_print=True) -> (float, [dict]): analyses = [] objective = 0.0 n_days = config['n_days'] metric = config['metric'] if 'metric' in config else 'adjusted_daily_gain' if config['sliding_window_days'] == 0.0: sliding_window_days = n_days else: # sliding window n days should be greater than max hrs no fills sliding_window_days = min( n_days, max([ config['hrs_stuck_max_long'] * 2.1 / 24, config['hrs_stuck_max_shrt'] * 2.1 / 24, config['sliding_window_days'] ])) sample_size_ms = data[1][0] - data[0][0] max_span = config['max_span'] if 'max_span' in config else 0 max_span_ito_n_samples = int(max_span * 60 / (sample_size_ms / 1000)) for z, data_slice in enumerate( iter_slices(data, sliding_window_days, max_span=int(round(max_span)))): if len(data_slice[0]) == 0: print('debug b no data') continue try: packed = pack_config(config) fills, stats = backtest(packed, data_slice) except Exception as e: print(e) break _, _, analysis = analyze_fills(fills, stats, config) analysis['score'], do_break, line = objective_function(analysis, config, metric=metric) analysis['score'] *= (analysis['n_days'] / config['n_days']) analyses.append(analysis) objective = np.sum([e['score'] for e in analyses]) * max( 1.01, config['reward_multiplier_base'])**(z + 1) analyses[-1]['objective'] = objective line = ( f'{str(z).rjust(3, " ")} adg {analysis["average_daily_gain"]:.4f}, ' f'bkr {analysis["closest_bkr"]:.4f}, ' f'eqbal {analysis["eqbal_ratio_min"]:.4f} n_days {analysis["n_days"]:.1f}, ' f'score {analysis["score"]:.4f}, objective {objective:.4f}, ' f'hrs stuck ss {str(round(analysis["hrs_stuck_max"], 1)).zfill(4)}, ' ) + line if do_print: print(line) if do_break: break return objective, analyses
def simple_sliding_window_wrap(config, ticks): sliding_window_size = config[ 'sliding_window_size'] if 'sliding_window_size' in config else 0.4 n_windows = config[ 'n_sliding_windows'] if 'n_sliding_windows' in config else 4 test_full = config['test_full'] if 'test_full' in config else False results = [] for ticks_slice in iter_slices(ticks, sliding_window_size, n_windows, yield_full=test_full): try: fills, _, did_finish = backtest(config, ticks_slice) except Exception as e: print('debug a', e, config) try: _, result_ = analyze_fills(fills, config, ticks_slice[-1][2]) except Exception as e: print('b', e) results.append(result_) if config['break_early_factor'] > 0.0 and \ (not did_finish or result_['closest_liq'] < config['minimum_liquidation_distance'] * (1 - config['break_early_factor']) or result_['max_hrs_no_fills'] > config['max_hrs_no_fills'] * (1 + config['break_early_factor']) or result_['max_hrs_no_fills_same_side'] > config['max_hrs_no_fills_same_side'] * (1 + config['break_early_factor'])): break if results: result = {} for k in results[0]: try: if k == 'closest_liq': result[k] = np.min([r[k] for r in results]) elif 'max_hrs_no_fills' in k: result[k] = np.max([r[k] for r in results]) else: result[k] = np.mean([r[k] for r in results]) except: result[k] = results[0][k] else: result = get_empty_analysis() try: objective = objective_function(result, 'average_daily_gain', config) except Exception as e: print('c', e) tune.report( objective=objective, daily_gain=result['average_daily_gain'], closest_liquidation=result['closest_liq'], max_hrs_no_fills=result['max_hrs_no_fills'], max_hrs_no_fills_same_side=result['max_hrs_no_fills_same_side'])
def do_opt_portfolio_test(self, *, start_date=None, end_date=None, loc=-1, foldername='', indus_neutral=False): # 生成调仓日 self.generate_holding_days(loc=loc, start_date=start_date, end_date=end_date) # 初始化持仓矩阵 self.initialize_position(self.strategy_data.stock_price.ix[0, self.holding_days, :]) # 过滤不可交易数据 self.strategy_data.handle_stock_pool(shift=True) self.strategy_data.discard_uninv_data() self.factor_return = self.factor_return.where(self.strategy_data.if_tradable['if_inv'], np.nan) # # 投资域为全市场时的tricky解法, 只保留有alpha, 且在benchmark中的股票 # self.factor_return = self.factor_return.mask(np.logical_and(self.strategy_data.benchmark_price.iloc[0]>0, # self.factor_return.isnull()), 0) # 解优化组合 self.construct_optimized_portfolio(indus_neutral=indus_neutral) # 如果没有路径名, 则自己创建一个 if not os.path.exists(str(os.path.abspath('.')) + '/' + foldername + self.strategy_data.stock_pool + '/'): os.makedirs(str(str(os.path.abspath('.')) + '/' + foldername + self.strategy_data.stock_pool + '/')) # 建立画pdf的对象 self.pdfs = PdfPages(str(os.path.abspath('.')) + '/' + foldername + self.strategy_data.stock_pool + '/allfigs.pdf') # 进行回测 self.bkt_obj = backtest(self.position, bkt_start=start_date, bkt_end=end_date, bkt_benchmark_data='ClosePrice_adj_'+self.strategy_data.stock_pool) self.bkt_obj.execute_backtest() self.bkt_obj.get_performance(foldername=foldername + self.strategy_data.stock_pool, pdfs=self.pdfs) # 做真实情况下的超额归因 pa_benchmark_weight = data.read_data(['Weight_' + self.strategy_data.stock_pool], ['Weight_' + self.strategy_data.stock_pool]) pa_benchmark_weight = pa_benchmark_weight['Weight_' + self.strategy_data.stock_pool] # pa_benchmark_weight = data.read_data(['Weight_hs300'], # ['Weight_hs300']) # pa_benchmark_weight = pa_benchmark_weight['Weight_hs300'] self.bkt_obj.get_performance_attribution(benchmark_weight=pa_benchmark_weight, show_warning=False, pdfs=self.pdfs, is_real_world=True, foldername=foldername + self.strategy_data.stock_pool, real_world_type=2, enable_read_base_expo=True, enable_read_pa_return=True, base_stock_pool=self.strategy_data.stock_pool) self.pdfs.close()
def main(strategy, scoreFile, scoreColumn): df = pd.read_csv(scoreFile) df.sort_values(['tradeDate', scoreColumn], inplace=True, ascending=False) dfdt = utils_common.groupDt(df) backtest.backtest(1000000, '0000-00-00', '9999-99-99', strategy, dfdt) pass
# backtest results assets = {} returns = {} for key, model in models.items(): print(f'Optimizing {key}...') data = sp500 if key == 'Momentum': lookback_period = 12 elif key == 'ResidualMomentum': lookback_period = 36 else: lookback_period = 36 start = time.time() a, r = backtest(model=model, invest_start=invest_start, invest_period=invest_period, lookback_period=lookback_period, rebalance_period=rebalance_period, historical_data=data) end = time.time() print(f'Optimization took: {end - start:8.4f}sec') assets[key] = a returns[key] = r pfo_rets = pd.DataFrame(returns, index=pd.period_range(invest_start, freq='M', periods=invest_period)) # get S&P500 index pfo_rets['S&P500'] = get_sp500_index(invest_start, invest_period) print( '***************************** Optimization summary *****************************' )
import backtest if __name__ == "__main__": testStock = ["AAPL"] newTest = backtest.backtest(testStock, start="2020-05-30", end="2020-12-30") newTest.algo_1(risk=0.05, profit=0.10, starting_capital=500, testing=False) print("\n\n" + newTest.get_summary())
def sf_test_multiple_pools_parallel(factor=None, *, direction='+', bb_obj=None, discard_factor=(), folder_name=None, stock_pools=('all', 'hs300', 'zz500', 'zz800'), bkt_start=None, bkt_end=None, select_method=0, do_bb_pure_factor=False, do_pa=False, do_factor_corr_test=False, do_active_pa=False, holding_freq='w', do_data_description=False, loc=-1): cp_adj = data.read_data(['ClosePrice_adj']) cp_adj = cp_adj['ClosePrice_adj'] temp_position = position(cp_adj) # 先要初始化bkt对象 bkt_obj = backtest(temp_position, bkt_start=bkt_start, bkt_end=bkt_end, buy_cost=1.5 / 1000, sell_cost=1.5 / 1000) # 建立bb对象,否则之后每次循环都要建立一次新的bb对象 if bb_obj is None: bb_obj = barra_base() # 外部传入的bb对象,要检测其股票池是否为all,如果不是all,则输出警告,因为可能丢失了数据 elif bb_obj.bb_data.stock_pool != 'all': print( 'The stockpool of the barra_base obj from outside is NOT "all", be aware of possibile' 'data loss due to this situation!\n') def single_task(stock_pool): # curr_sf = single_factor_strategy() from intangible_info import intangible_info_earnings curr_sf = intangible_info_earnings() # 进行当前股票池下的单因子测试 # 注意bb obj进行了一份深拷贝,这是因为在业绩归因的计算中,会根据不同的股票池丢弃数据,导致数据不全,因此不能传引用 # 对bkt obj做了同样的处理,这是因为尽管bkt obj不会被改变,但是多进程同时操作可能出现潜在的问题 curr_sf.single_factor_test(stock_pool=stock_pool, factor=factor, loc=loc, direction=direction, folder_name=folder_name, bkt_obj=copy.deepcopy(bkt_obj), base_obj=copy.deepcopy(bb_obj), discard_factor=discard_factor, bkt_start=bkt_start, bkt_end=bkt_end, select_method=select_method, do_base_pure_factor=do_bb_pure_factor, holding_freq=holding_freq, do_pa=do_pa, do_active_pa=do_active_pa, do_data_description=do_data_description, do_factor_corr_test=do_factor_corr_test) import multiprocessing as mp mp.set_start_method('fork') # 根据股票池进行循环 for stock_pool in stock_pools: p = mp.Process(target=single_task, args=(stock_pool, )) p.start()
grid = (klines['close'] - fma) / atr return grid def buy_signal(self, index_code): rsrs = self.get_rsrs_value(index_code) return rsrs > 1 and self.buy_filter(index_code) def sell_signal(self, index_code): rsrs = self.get_rsrs_value(index_code) return rsrs < -1 and self.sell_filter(index_code) def buy_filter(self, index_code): grid = self.get_grid(index_code) return grid.values[-1] > 1 def sell_filter(self, index_code): grid = self.get_grid(index_code) return grid.values[-1] < -1 if __name__ == '__main__': import backtest import account acc = account.IndexAccount(data=backtest.get_datasource()) stra = RSRS_Strategy(['399300.SZ'], account=acc) report = backtest.backtest(stra, start='20160101', end='20181231') report.show()
def backtest_wrap(config_: dict, ticks_caches: dict): """ loads historical data from disk, runs backtest and returns relevant metrics """ config = { **{ "long": deepcopy(config_["long"]), "short": deepcopy(config_["short"]) }, **{ k: config_[k] for k in [ "starting_balance", "latency_simulation_ms", "symbol", "market_type", "config_no", ] }, **{k: v for k, v in config_["market_specific_settings"].items()}, } if config["symbol"] in ticks_caches: ticks = ticks_caches[config["symbol"]] else: ticks = np.load(config_["ticks_cache_fname"]) try: fills_long, fills_short, stats = backtest(config, ticks) longs, shorts, sdf, analysis = analyze_fills(fills_long, fills_short, stats, config) pa_distance_mean_long = analysis["pa_distance_mean_long"] pa_distance_mean_short = analysis["pa_distance_mean_short"] PAD_std_long = analysis["pa_distance_std_long"] PAD_std_short = analysis["pa_distance_std_short"] adg_long = analysis["adg_long"] adg_short = analysis["adg_short"] adg_DGstd_ratio_long = analysis["adg_DGstd_ratio_long"] adg_DGstd_ratio_short = analysis["adg_DGstd_ratio_short"] """ with open("logs/debug_harmonysearch.txt", "a") as f: f.write(json.dumps({"config": denumpyize(config), "analysis": analysis}) + "\n") """ logging.debug( f"backtested {config['symbol']: <12} pa distance long {pa_distance_mean_long:.6f} " + f"pa distance short {pa_distance_mean_short:.6f} adg long {adg_long:.6f} " + f"adg short {adg_short:.6f} std long {PAD_std_long:.5f} " + f"std short {PAD_std_short:.5f}") except Exception as e: logging.error(f'error with {config["symbol"]} {e}') logging.error("config") traceback.print_exc() adg_long = adg_short = adg_DGstd_ratio_long = adg_DGstd_ratio_short = 0.0 pa_distance_mean_long = pa_distance_mean_short = PAD_std_long = PAD_std_short = 100.0 with open(make_get_filepath("tmp/harmony_search_errors.txt"), "a") as f: f.write( json.dumps([time(), "error", str(e), denumpyize(config)]) + "\n") return { "pa_distance_mean_long": pa_distance_mean_long, "pa_distance_mean_short": pa_distance_mean_short, "adg_DGstd_ratio_long": adg_DGstd_ratio_long, "adg_DGstd_ratio_short": adg_DGstd_ratio_short, "pa_distance_std_long": PAD_std_long, "pa_distance_std_short": PAD_std_short, "adg_long": adg_long, "adg_short": adg_short, }
hls = [10, 40, 100] for quotes, trades in data: features.label_data(quotes, label_hls=hls) features.add_ema(quotes, halflives=hls) features.add_dema(quotes, halflives=hls) features.add_momentum(quotes, halflives=hls) features.add_log_return_ema(quotes, halflives=hls) features.add_trade_momentum(quotes, trades, bar_width='second') quotes_list, trades_list = zip(*data) quotes = pd.concat(quotes_list) trades = pd.concat(trades_list) pnl_history, order_history = backtest(magic_strategy, quotes, trades, transaction_costs=0.005, slippage_rate=0.25, delay_fill=True) fig, axes = plt.subplots(nrows=4) axes[0].plot(quotes['DATE_TIME'].values, quotes['price'].values) for hl in hls: axes[0].plot(quotes['DATE_TIME'].values, quotes['EMA_{}'.format(hl)].values) long_orders = filter(lambda x: x[2] > 0, order_history) short_orders = filter(lambda x: x[2] < 0, order_history) long_order_times = map(lambda x: x[0], long_orders) short_order_times = map(lambda x: x[0], short_orders) long_order_prices = map(lambda x: x[3], long_orders) short_order_prices = map(lambda x: x[3], short_orders)
def get_lines(): count = 0 game_list = [] r = {} while type(r) != list: league = input('What league? ') r = requests.get( "https://www.bovada.lv/services/sports/event/v2/events/A/description/football/" + league, verify=False).json() print(BORDER) data = r[0] for game in data: for team in data['events']: try: count += 1 EpochTime = team['startTime'] Epoch = datetime.datetime.fromtimestamp(EpochTime / 1e3) date = Epoch.strftime('%m-%d-%Y %H:%M:%S') team_1 = team['competitors'][0]['name'].rstrip() team_2 = team['competitors'][1]['name'].rstrip() if team_1 in game_list: break else: try: odd_1_1 = team['displayGroups'][0]['markets'][1][ 'outcomes'][0]['price']['handicap'] except KeyError: odd_1_1 = None try: odd_1_2 = team['displayGroups'][0]['markets'][1][ 'outcomes'][0]['price']['american'] except KeyError: odd_1_2 = None try: odd_2_1 = team['displayGroups'][0]['markets'][1][ 'outcomes'][1]['price']['handicap'] except KeyError: odd_2_1 = None try: odd_2_2 = team['displayGroups'][0]['markets'][1][ 'outcomes'][1]['price']['american'] except KeyError: odd_2_2 = None try: ML_2 = team['displayGroups'][0]['markets'][0][ 'outcomes'][0]['price']['american'] except KeyError: ML_2 = None try: ML_1 = team['displayGroups'][0]['markets'][0][ 'outcomes'][1]['price']['american'] except KeyError: ML_1 = None try: o = team['displayGroups'][0]['markets'][2]['outcomes'][ 0]['price']['handicap'] except KeyError: o = None try: o_1 = team['displayGroups'][0]['markets'][2][ 'outcomes'][0]['price']['american'] except KeyError: o_1 = None try: u = team['displayGroups'][0]['markets'][2]['outcomes'][ 1]['price']['handicap'] except KeyError: o = None try: u_1 = team['displayGroups'][0]['markets'][2][ 'outcomes'][1]['price']['american'] except KeyError: o_1 = None if team['displayGroups'][0]['markets'][0]['period'][ 'live'] is True: print('{0} | {1}'.format(count, 'LIVE!')) else: print('{0} |'.format(count)) print(date) print("{0} ({1},{2}) | {3} | o({4},{5})".format( team_2, odd_1_1, odd_1_2, ML_2, o, o_1)) print("{0} ({1},{2}) | {3} | u({4},{5})".format( team_1, odd_2_1, odd_2_2, ML_1, u, u_1)) if team['competitors'][0]['home'] is True: print(get_weather(abbrev(team_1, 'city'), date)) else: print(get_weather(abbrev(team_2, 'city'), date)) print(SUBSET) game_list.append(team_1) game_info = [{ 'Time': date, 'Away Team': team_2, 'odds': odd_1_1, 'Win': odd_1_2, 'Money Line': ML_2, 'Over': o, 'Over Line': o_1, 'Under': u, 'Under Line': u_1, 'Home Team': team_1, 'odds': odd_2_1, 'Win': odd_2_2, 'Money Line': ML_1 }] backtest(game_info) except KeyError: odd_1_1 = None except IndexError: pass
def main(strategy,scoreFile,scoreColumn): df = pd.read_csv(scoreFile); df.sort_values(['tradeDate',scoreColumn],inplace=True,ascending=False); dfdt = utils_common.groupDt(df); backtest.backtest(1000000,'0000-00-00','9999-99-99',strategy,dfdt); pass;
def sf_test_multiple_pools(factor='default', *, direction='+', bb_obj='Empty', discard_factor=[], holding_freq='m', stock_pools=['all', 'hs300', 'zz500', 'zz800'], bkt_start='default', bkt_end='default', select_method=0, do_bb_pure_factor=False, do_active_bb_pure_factor=False, do_pa=False, do_active_pa=False, do_data_description=False): # 如果传入的是str,则将其传入到single factor test中去让其自己处理,如果是dataframe,则直接传入因子 # 注意:这里的因子数据并不储存到self.strategy_data.factor中,因为循环股票池会丢失数据 if type(factor) != str: factor_data = data.read_data([factor], [factor], shift=True) factor = factor_data[factor] # 初始化一个持仓对象,以用来初始化backtest对象,索引以factor为标准 temp_position = position(factor) else: # 如过传入的是string, 则读取closeprice_adj来初始化backtest对象 cp_adj = data.read_data(['ClosePrice_adj']) cp_adj = cp_adj['ClosePrice_adj'] temp_position = position(cp_adj) # 先要初始化bkt对象 bkt_obj = backtest(temp_position, bkt_start=bkt_start, bkt_end=bkt_end, buy_cost=1.5 / 1000, sell_cost=1.5 / 1000) # 建立bb对象,否则之后每次循环都要建立一次新的bb对象 if bb_obj == 'Empty': bb_obj = barra_base() bb_obj.just_get_sytle_factor() # 外部传入的bb对象,要检测其股票池是否为all,如果不是all,则输出警告,因为可能丢失了数据 elif bb_obj.bb_data.stock_pool != 'all': print( 'The stockpool of the barra_base obj from outside is NOT "all", be aware of possibile' 'data loss due to this situation!\n') # 根据股票池进行循环 for stock_pool in stock_pools: # 建立单因子测试对象 # curr_sf = single_factor_strategy() from analyst_coverage import analyst_coverage curr_sf = analyst_coverage() # 进行当前股票池下的单因子测试 # 注意bb obj进行了一份深拷贝,这是因为在业绩归因的计算中,会根据不同的股票池丢弃数据,导致数据不全,因此不能传引用 # 对bkt obj做了同样的处理,尽管这里并不是必要的 curr_sf.single_factor_test( factor=factor, direction=direction, bkt_obj=copy.deepcopy(bkt_obj), bb_obj=copy.deepcopy(bb_obj), discard_factor=discard_factor, bkt_start=bkt_start, bkt_end=bkt_end, holding_freq=holding_freq, stock_pool=stock_pool, select_method=select_method, do_bb_pure_factor=do_bb_pure_factor, do_active_bb_pure_factor=do_active_bb_pure_factor, do_pa=do_pa, do_active_pa=do_active_pa, do_data_description=do_data_description)
def run(self): bc = deepcopy(self.bc) balance_and_pos = { "starting_balance": bc["starting_balance"], "long_pprice": 0.0, "long_psize": 0.0, "shrt_pprice": 0.0, "shrt_psize": 0.0, } all_daily_returns = [] for k, split in enumerate(self): train = split["train"] test = split["test"] print("*** STARTIN BALANCE", balance_and_pos["starting_balance"]) self.update_config(bc, train, balance_and_pos) analysis = backtest_tune( self.ticks[train["start_idx"]:train["end_idx"]], bc) candidate = clean_result_config(analysis.best_config) self.update_config(bc, test) fills, stats, did_finish = backtest( candidate, self.ticks[test["start_idx"]:test["end_idx"]]) _, _, result = analyze_backtest( fills, stats, bc, ) # Update the balance and positions with the last filled values of the testing run balance_and_pos = { key: fills[-1][key] for key in (balance_and_pos.keys() & fills[-1].keys()) } balance_and_pos["starting_balance"] = stats[-1][ "balance"] # Same as fills all_daily_returns.append( result["returns_daily"]) # stats is more accurate than fills print("*** EQUITY", stats[-1]["equity"], all_daily_returns, "\n") # json.dump: candidate, result, stats, fills # we can load these files and generate plots/reports later # with open(f"/tmp/candidate_test_{k}.json", "w") as f: # json.dump(candidate, f) # with open(f"/tmp/res_test_{k}.json", "w") as f: # json.dump(result, f) # with open(f"/tmp/stats_test_{k}.json", "w") as f: # json.dump(stats, f) # with open(f"/tmp/fills_test_{k}.json", "w") as f: # json.dump(fills, f) returns_gmean = np.exp(np.mean( np.log(np.array(all_daily_returns) + 1))) - 1 print("Geometrical mean of all the daily returns", returns_gmean)
def do_opt_portfolio_test(self, *, start_date=None, end_date=None, loc=-1, foldername='', indus_neutral=False): # 生成调仓日 self.generate_holding_days(loc=loc, start_date=start_date, end_date=end_date) # 初始化持仓矩阵 self.initialize_position( self.strategy_data.stock_price.ix[0, self.holding_days, :]) # 过滤不可交易数据 self.strategy_data.handle_stock_pool(shift=True) self.strategy_data.discard_uninv_data() self.factor_return = self.factor_return.where( self.strategy_data.if_tradable['if_inv'], np.nan) # # 投资域为全市场时的tricky解法, 只保留有alpha, 且在benchmark中的股票 # self.factor_return = self.factor_return.mask(np.logical_and(self.strategy_data.benchmark_price.iloc[0]>0, # self.factor_return.isnull()), 0) # 解优化组合 self.construct_optimized_portfolio(indus_neutral=indus_neutral) # 将优化组合中小于万分之一的持仓扔掉 self.position.holding_matrix = self.position.holding_matrix.where( self.position.holding_matrix >= 1e-4, 0) # 如果没有路径名, 则自己创建一个 if not os.path.exists( str(os.path.abspath('.')) + '/' + foldername + self.strategy_data.stock_pool + '/'): os.makedirs( str( str(os.path.abspath('.')) + '/' + foldername + self.strategy_data.stock_pool + '/')) # 建立画pdf的对象 self.pdfs = PdfPages( str(os.path.abspath('.')) + '/' + foldername + self.strategy_data.stock_pool + '/allfigs.pdf') # 进行回测 self.bkt_obj = backtest(self.position, bkt_start=start_date, bkt_end=end_date, bkt_benchmark_data='ClosePrice_adj_' + self.strategy_data.benchmark) self.bkt_obj.execute_backtest() self.bkt_obj.get_performance(foldername=foldername + self.strategy_data.stock_pool, pdfs=self.pdfs) # 根据策略的超额净值, 可以计算策略的实现的超额收益波动率, 对比实现波动率和预测波动率, 可以看出风险预测能力 # 由于是周5换仓, 因此实现的区间为周5到下周4, 标签选择周5, 因此选择的resample区间为周五开始, 周五结束 # 闭区间选择为left, 即这周五, 标签也选择为left, 即这周五, 这样就能和预测风险的标签相吻合 active_nav_ret_std = self.bkt_obj.bkt_performance.active_nav.pct_change(). \ resample('w-fri', closed='left', label='left').std().mul(np.sqrt(252)) # 统计量为实现波动率除以预测波动率 self.risk_pred_ratio = active_nav_ret_std / self.forecasted_vol # 实现波动率储存起来以供参考 self.realized_vol = active_nav_ret_std # 打印统计量的均值和方差 str_risk = 'Risk forecast accuracy ratio, mean: {0}, std: {1}\n'. \ format(self.risk_pred_ratio.mean(), self.risk_pred_ratio.std()) print(str_risk) # 根据优化组合算每期组合的预期alpha self.forecasted_alpha = self.position.holding_matrix.mul( self.factor_return.reindex( index=self.position.holding_matrix.index)).sum(1) # 打印组合的预期alpha均值和方差 str_alpha = 'Alpha forecast, mean: {0}, std: {1}\n'. \ format(self.forecasted_alpha.mean(), self.forecasted_alpha.std()) print(str_alpha) # 将风险预测统计量, 预期alpha, 以及风险厌恶系数等量写入txt文件 target_str = str_risk + str_alpha target_str += 'Cov Mat risk aversion: {0}, Spec Var risk aversion: {1}\n'. \ format(self.cov_risk_aversion, self.spec_risk_aversion) with open(str(os.path.abspath('.')) + '/' + foldername + self.strategy_data.stock_pool + '/performance.txt', 'a', encoding='GB18030') as text_file: text_file.write(target_str) # 做真实情况下的超额归因 pa_benchmark_weight = data.read_data( 'Weight_' + self.strategy_data.benchmark).fillna(0.0) # pa_benchmark_weight = data.read_data(['Weight_hs300'], # ['Weight_hs300']) # pa_benchmark_weight = pa_benchmark_weight['Weight_hs300'] self.bkt_obj.get_performance_attribution( benchmark_weight=pa_benchmark_weight, show_warning=False, pdfs=self.pdfs, is_real_world=True, foldername=foldername + self.strategy_data.stock_pool, real_world_type=2, enable_read_pa_return=True, base_stock_pool=self.strategy_data.stock_pool) self.pdfs.close()
s0, r, var_type, method, window_length, VaR_Horizon, VaRp, evaluation, simulations = loadInputs() stocks, stock_weights = loadStockInputs() options, option_type, option_wgt = loadOptionInputs() stock_prices, stock_dates = loadPrices(stocks) implied_vol, option_dates = loadOptions(options) # Calibrate Portfolio stock_prices, portVal, portDt = calibratePortfolio(stocks, options, option_type, option_wgt, r, stock_prices, stock_dates, option_dates, stock_weights, implied_vol, s0) # Calculate VaR, Loss and Backtest if var_type == 'Par GBM': var = gbmVaR(stock_weights, method, window_length, portVal, s0, VaRp, VaR_Horizon) bt, loss = backtest(stocks, options, implied_vol, option_type, option_wgt, r, stock_prices, var, stock_weights, VaR_Horizon, evaluation, s0) elif var_type == 'Par BM': var = ParVaR(stocks, options, option_type, option_wgt, implied_vol, r, stock_prices, stock_weights, s0, VaR_Horizon, window_length, evaluation, VaRp, method) bt, loss = backtest(stocks, options, implied_vol, option_type, option_wgt, r, stock_prices, var, stock_weights, VaR_Horizon, evaluation, s0) elif var_type == 'Hist': var = HistVaR(stocks, options, implied_vol, option_type, option_wgt, r, stock_prices, stock_weights, s0, VaR_Horizon, window_length, evaluation, VaRp) bt, loss = backtest(stocks, options, implied_vol, option_type, option_wgt, r, stock_prices, var, stock_weights, VaR_Horizon, evaluation, s0) elif var_type == 'MC GBM': var = MonteCarloVaR_GBM(portVal, method, window_length, VaR_Horizon, evaluation, VaRp, s0, simulations) bt, loss = backtest(stocks, options, implied_vol, option_type, option_wgt, r, stock_prices, var, stock_weights, VaR_Horizon, evaluation, s0) elif var_type == 'MC BM': var = MonteCarloVaR(stocks, options, option_type, option_wgt, implied_vol, r, stock_prices, stock_weights, s0, VaR_Horizon, window_length, evaluation, VaRp, method, simulations) bt, loss = backtest(stocks, options, implied_vol, option_type, option_wgt, r, stock_prices, var, stock_weights, VaR_Horizon, evaluation, s0) else: print('Incorrect VaR Type. Check Inputs')
cv_split = 0.05 ticker = input("Choose a Ticker to Model: ") df, Close_list = prepare_data(ticker) X_full2d, X_full3d, Y, X_train2d, X_test2d, X_train3d, X_test3d, y_train, y_test, split_value = flatten_dataset( df, test_size=cv_split) model, history, predictions, targets = lstm_train(X_full2d, X_full3d, Y, X_train2d, X_test2d, X_train3d, X_test3d, y_train, y_test, batch_size=100, epochs=10) backtest(predictions, 10000, Close_list, targets, ticker, split_value, sell_tolerance=0.5, buy_tolerance=0.5)
def main(strategy, startDt, endDt, initMoney): decFactor = utils_server.getDecFactors(startDt, endDt) decFactor = {k: filterDf(df) for k, df in decFactor.items()} backtest.backtest(initMoney, startDt, endDt, strategy, decFactor) pass
from get_dayprice import collect_dayprice_everyday from generate_training_test_data import generate_training_test_data from generate_ARIMA_model import generate_ARIMA_model from backtest import backtest if __name__ == '__main__': collect_dayprice_everyday() generate_training_test_data() generate_ARIMA_model() backtest()
def main(argv): period = 0 pair = '' kpair = '' linearPair = '' checkLastPrice = False showCurrentBalance = False forecast = False testSymbol = '' buyParams = '' sellParams = '' cancelParams = '' predictPair = '' backtestParams = '' try: opts, args = getopt.getopt(argv, "efwlhp:c:k:m:t:b:s:x:a:r:", [ "period=", "asset=", "klines=", "model=", "test=", "buy=", "sell=", "cancel=", "predict=", "btest=" ]) except getopt.GetoptError: help() sys.exit(2) for opt, arg in opts: if opt in ("-p", "--period"): period = arg elif opt in ("-c", "--asset"): pair = arg elif opt == '-h': help() elif opt == '-l': checkLastPrice = True elif opt == '-w': showCurrentBalance = True elif opt in ("-k", "--klines"): kpair = arg elif opt in ("-m", "--model"): linearPair = arg elif opt == '-f': forecast = True elif opt == '-e': exchange_info = client.get_exchange_info() rate_limits = exchange_info['rateLimits'] for r in rate_limits: print( f"{r['rateLimitType']} per {r['interval']}: {r['limit']}") elif opt in ("-t", "--test"): testSymbol = arg elif opt in ("-b", "--buy"): buyParams = arg elif opt in ("-s", "--sell"): sellParams = arg elif opt in ("-x", "--cancel"): cancelParams = arg elif opt in ("-a", "--predict"): predictPair = arg elif opt in ("-r", "--btest"): backtestParams = arg while True: if (backtestParams): params_arr = backtestParams.split("_") bt = backtest.backtest(client, params_arr[0], params_arr[1], params_arr[2]) bt.testModel() if (cancelParams): trade.cancelAllOrders(client, cancelParams) if (sellParams): params_arr = sellParams.split("_") print(params_arr) trade.sellOrder(client, params_arr[0], params_arr[1], params_arr[2]) if (buyParams): params_arr = buyParams.split("_") print(params_arr) trade.buyOrder(client, params_arr[0], params_arr[1], params_arr[2]) if (testSymbol): print(datetime.now()) t0 = time.time() if (testSymbol == 'ALL') or (testSymbol == 'all'): filename1 = datetime.now().strftime("%Y%m%d-%H%M%S") #open('output.txt', 'w').close() sys.stdout = open(f'output/{filename1}.txt', 'w') print(datetime.now()) prices = client.get_all_tickers() marketsymbols = [] ta = [] for symbol in prices: if symbol['symbol'][-3:] == 'BTC': marketsymbols.append(symbol['symbol']) for symbol in marketsymbols: ta.append(test.testMethod(client, symbol, True)) ta = list(filter(None.__ne__, ta)) print("Stoch K lower than 20") for t in ta: if (t['slowk'] <= 20): if (t['macd'] <= t['macdsignal']): if (t['price'] <= t['middleband']): test.printOutputs(t) print("\n-------------------------------") print("Stoch K lower than D") for t in ta: if (t['slowk'] <= 80 and t['slowk'] <= t['slowd']): if (t['macd'] <= t['macdsignal']): if (t['price'] <= t['middleband']): test.printOutputs(t) sys.stdout.close() sys.stdout = sys.__stdout__ print(f'Results displayed in output/{filename1}.txt') else: t0 = time.time() test.printOutputs(test.testMethod(client, testSymbol, False)) t1 = time.time() total = t1 - t0 #print(total) t1 = time.time() total = t1 - t0 print(f"Finished in: {total}") if (checkLastPrice): printLastMarketPrices() if (showCurrentBalance): printCurrentAssets() if (kpair): printKlines(kpair) if (forecast): prices = client.get_all_tickers() marketsymbols = [] for symbol in prices: if symbol['symbol'][-3:] == 'BTC': marketsymbols.append(symbol['symbol']) for symbol in marketsymbols: candles = client.get_klines( symbol=symbol, interval=Client.KLINE_INTERVAL_5MINUTE) depth = client.get_order_book(symbol=symbol) predict.linearRegressionModel(symbol, candles, depth) if (predictPair): candles = client.get_klines(symbol=predictPair, interval=Client.KLINE_INTERVAL_4HOUR, limit=100) depth = client.get_order_book(symbol=predictPair) predict.linearRegressionModel(predictPair, candles, depth) if (pair): printCurrentAssetBalance(pair) # #printCurrentAssets(info) #printLastPrices(prices) if (int(period) > 0): time.sleep(int(period)) else: sys.exit()
def main(strategy, startDt,endDt,initMoney): decFactor = utils_server.getDecFactors(startDt,endDt); decFactor = {k:filterDf(df) for k,df in decFactor.items()} backtest.backtest(initMoney,startDt,endDt,strategy,decFactor); pass;
def main(): ''' 标的 ''' code = '000300' ''' 个股 ''' code = '000016' img_path = './img/' + code train_s_date = '2005-01-01' # 训练集时间范围 train_e_date = '2010-12-31' test_s_date = '2011-01-01' # 测试集时间范围 test_e_date = '2017-12-31' # test_e_date = datetime.datetime.now().strftime('%Y-%m-%d') shutil.rmtree(img_path) os.mkdir(img_path) is_feature_select = False # 是否特征选择 is_standardize = False # 是否标准化 maxperiod = 33 # 生成属性的最大周期 index_hist_train_df = dao.get_local_bar_data(code, train_s_date, train_e_date) # 获取训练集 index_hist_test_df = dao.get_local_bar_data(code, test_s_date, test_e_date) # 获取测试集 index_hist_train_df.sort_index(inplace=True) # 按照日期排序 index_hist_test_df.sort_index(inplace=True) # 按照日期排序 train_datelist = pd.to_datetime( index_hist_train_df.close.index[maxperiod + 1:]) # 获取训练集的日期列表 train_closeidx = index_hist_train_df.close[maxperiod + 1:] # 获取训练集每日收盘价 test_datelist = pd.to_datetime( index_hist_test_df.close.index[maxperiod + 1:]) # 获取测试集的日期列表 test_closeidx = index_hist_test_df.close[maxperiod + 1:] # 获取测试集每日收盘价 # train train_X, train_logreturn = features.gen_attrs(img_path, index_hist_train_df, maxperiod) # 生成属性 # test test_X, test_logreturn = features.gen_attrs(img_path, index_hist_test_df, maxperiod) # 生成属性 # train hmm model hmm = GaussianHMM(n_components=5, covariance_type='diag', n_iter=1000000, algorithm='viterbi', random_state=0) hmm = hmm.fit(train_X) # 训练HMM latent_states_sequence_train = simulate_predict(train_X, hmm) # 训练集模拟每天预测一天 draw_result(img_path, train_datelist, train_closeidx, latent_states_sequence_train, hmm) # 训练集状态图 draw_back(img_path, train_datelist, train_logreturn, latent_states_sequence_train, hmm) # 训练集收益曲线 latent_states_sequence_test = simulate_predict(test_X, hmm) # 测试集模拟每天预测一天 latent_states_sequence_test[:-1].tofile('states_sequence.csv', sep=',') # 保存模拟预测每日状态 draw_result(img_path, test_datelist, test_closeidx, latent_states_sequence_test, hmm) # 测试集状态图 selected_states = draw_back(img_path, test_datelist, test_logreturn, latent_states_sequence_test, hmm) # 测试集收益曲线 print(selected_states) joblib.dump(hmm, 'model/hmm_50.m') # 本地化模型 # 本地回测 latent_states_sequence_backtest = latent_states_sequence_test[ len(latent_states_sequence_train):] import backtest backtest.backtest(latent_states_sequence_backtest, [0, 1, 2], dao.get_local_bar_data(code, '2015-01-01', '2017-12-31')) # joblib.dump(min_max_scaler, 'model/std.m') # 数据标准化模型 features.gen_attrs( img_path, dao.get_local_bar_data(code, '2010-01-01', '2017-12-31'), 10)
def single_factor_test(self, *, factor='default', direction='+', bkt_obj='Empty', bb_obj='Empty', pa_benchmark_weight='default', discard_factor=[], bkt_start='default', bkt_end='default', stock_pool='all', select_method=0, do_pa=True, do_active_pa=False, do_bb_pure_factor=False, do_active_bb_pure_factor=False, holding_freq='m', do_data_description=False): ################################################################################################### # 生成调仓日和生成可投资标记是第一件事, 因为之后包括因子构建的函数都要用到它 # 生成调仓日 if self.holding_days.empty: self.generate_holding_days(holding_freq=holding_freq) # 将策略的股票池设置为当前股票池 self.strategy_data.stock_pool = stock_pool # 根据股票池生成标记 self.strategy_data.handle_stock_pool(shift=True) ################################################################################################### # 第二部分是读取或生成要研究的因子 # 如果传入的是str,则读取同名文件,如果是dataframe,则直接传入因子 if type(factor) == str: if factor != 'default': self.read_factor_data([factor], [factor], shift=True) else: # 如果传入的是'default', 那么首先看策略类本身是否有内部构建其因子的函数 self.construct_factor() # 检测是否已经有因子存在,1. 因子是由策略类内部自身构建的 # 2. 有可能该实例化的类已经有了计算好的要测试的因子 if self.strategy_data.factor.shape[0] >= 1: print( 'The factor has been set to be the FIRST one in strategy_data.factor\n' ) elif self.strategy_data.factor_expo.shape[0] >= 1: self.strategy_data.factor = self.strategy_data.factor_expo print( 'The factor data has been copied from factor_expo data, and the factor will be' 'the FIRST one in strategy_data.factor_expo\n') else: print( 'Error: No factor data, please try to specify a factor!\n') elif self.strategy_data.factor.empty: self.strategy_data.factor = pd.Panel({'factor_one': factor}) else: self.strategy_data.factor.iloc[0] = factor ################################################################################################### # 第三部分是除去不可投资的数据, 初始化或者重置策略持仓, # 处理barra base类, backtest类, 以及建立文件夹等零碎的事情 # 除去不可交易或不可投资的数据 # 注意,对策略数据的修改是永久性的,无法恢复,因此在使用过某个股票池的单因子测试后,对策略数据的再使用要谨慎 if self.strategy_data.stock_pool == 'all': self.strategy_data.discard_untradable_data() else: self.strategy_data.discard_uninv_data() # 初始化持仓或重置策略持仓 if self.position.holding_matrix.empty: self.initialize_position( self.strategy_data.factor.ix[0, self.holding_days, :]) else: self.reset_position() # 如果有传入的bb对象 if bb_obj == 'Empty': pass else: # 将bb的股票池改为当前股票池 bb_obj.bb_data.stock_pool = stock_pool # 根据股票池生成标记,注意:股票池数据不需要shift,因为这里的barrabase数据是用来事后归因的,不涉及策略构成 bb_obj.bb_data.handle_stock_pool(shift=False) # 将回测的基准改为当前的股票池,若为all,则用默认的基准值 if stock_pool != 'all': bkt_obj.reset_bkt_benchmark(['ClosePrice_adj_' + stock_pool]) # 如果没有文件夹,则建立一个文件夹 if not os.path.exists( str(os.path.abspath('.')) + '/' + self.strategy_data.stock_pool + '/'): os.makedirs( str(os.path.abspath('.')) + '/' + self.strategy_data.stock_pool + '/') # 建立画pdf的对象 self.pdfs = PdfPages( str(os.path.abspath('.')) + '/' + self.strategy_data.stock_pool + '/allfigs.pdf') ################################################################################################### # 第四部分为, 1. 若各策略类有对原始因子数据的计算等, 可以在data description中进行 # 2. 根据选择的一组因子base(可以是barra的, 也可以不是), 进行与当前因子的相关性检验 # 3. 根据选择的一组因子base, 对当前因子进行提纯, 注意尽管与2差不多, 但是这里使得2, 3可以选择不同的base以及提纯方法 # 4. 未来还可添加: 如果是基础财务因子, 还可以添加对净利润增长的预测情况 # 如果有对原始数据的表述,则进行原始数据表述 if do_data_description: self.data_description() print('Data description completed...\n') # # 根据某一base, 做当前因子与其他因子的相关性检验 # if do_factor_corr_test: # self.get_factor_corr_test() # 如果要做基于barra base的纯因子组合,则要对因子进行提纯 if do_bb_pure_factor: self.get_pure_factor( bb_obj, do_active_bb_pure_factor=do_active_bb_pure_factor) ################################################################################################### # 第五部分为, 1.根据不同的单因子选股策略, 进行选股 # 2. 对策略选出的股票进行回测, 画图 # 3. 如果有归因, 则对策略选出的股票进行归因 # 按策略进行选股 if select_method == 0: # 简单分位数选股 self.select_stocks(weight=1, direction=direction, select_ratio=[0.8, 1]) elif select_method == 1: # 分行业选股 self.select_stocks_within_indus(weight=2, direction=direction) elif select_method == 2 or select_method == 3: # 用构造纯因子组合的方法选股,2为组合自己是纯因子组合,3为组合相对基准是纯因子组合 # 首先和计算纯因子一样,要计算bb因子的暴露 if bb_obj.bb_data.factor_expo.empty: bb_obj.just_get_factor_expo() # 同样需要lag lag_bb_expo = bb_obj.bb_data.factor_expo.shift(1).reindex( major_axis=bb_obj.bb_data.factor_expo.major_axis) # 同样不能有country factor lag_bb_expo_no_cf = lag_bb_expo.drop('country_factor', axis=0) # # 构造纯因子组合,权重使用回归权重,即市值的根号 # 初始化temp weight为'Empty',即如果选股方法是2,则传入默认的benchmark weight temp_weight = 'Empty' if select_method == 2: # self.select_stocks_pure_factor_bb(bb_expo=lag_bb_expo_no_cf, reg_weight=np.sqrt( # self.strategy_data.stock_price.ix['FreeMarketValue']), direction=direction) self.select_stocks_pure_factor( base_expo=lag_bb_expo_no_cf, reg_weight=np.sqrt( self.strategy_data.stock_price.ix['FreeMarketValue']), direction=direction, benchmark_weight=temp_weight, is_long_only=False) if select_method == 3 and self.strategy_data.stock_pool == 'all': temp_weight = data.read_data(['Weight_zz500'], ['Weight_zz500'], shift=True) temp_weight = temp_weight['Weight_zz500'] elif select_method == 3 and self.strategy_data.stock_pool != 'all': # 注意股票池为非全市场时,基准的权重数据已经shift过了 temp_weight = self.strategy_data.benchmark_price.ix[ 'Weight_' + self.strategy_data.stock_pool] if select_method == 3: self.select_stocks_pure_factor( base_expo=lag_bb_expo_no_cf, reg_weight=np.sqrt( self.strategy_data.stock_price.ix['FreeMarketValue']), direction=direction, benchmark_weight=temp_weight, is_long_only=True) # ------------------------------------------------------------------------------------ # holding = pd.read_csv('HOLDING500.csv', index_col=0, parse_dates=True) # new_col = [] # for curr_stock in holding.columns: # new_col.append(curr_stock.zfill(6)) # holding.columns = new_col # self.position.holding_matrix = holding.reindex(self.position.holding_matrix.index, # self.position.holding_matrix.columns, method='ffill').fillna(0.0) # pass # ------------------------------------------------------------------------------------ # 如果有外来的backtest对象,则使用这个backtest对象,如果没有,则需要自己建立,同时传入最新持仓 if bkt_obj == 'Empty': bkt_obj = backtest(self.position, bkt_start=bkt_start, bkt_end=bkt_end) else: bkt_obj.reset_bkt_position(self.position) # 将回测的基准改为当前的股票池,若为all,则用默认的基准值 if stock_pool != 'all': bkt_obj.reset_bkt_benchmark(['ClosePrice_adj_' + stock_pool]) # 回测、画图、归因 bkt_obj.execute_backtest() bkt_obj.get_performance(foldername=stock_pool, pdfs=self.pdfs) # 如果要进行归因的话 if do_pa: # 如果指定了要做超额收益的归因,且有股票池,则用相对基准的持仓来归因 # 而股票池为全市场时的超额归因默认基准为中证500 if do_active_pa and self.strategy_data.stock_pool != 'all': # 注意:策略里的strategy_data里的数据都是shift过后的,而进行归因的数据和回测一样,不能用shift数据,要用当天最新数据 pa_benchmark_weight = data.read_data( ['Weight_' + self.strategy_data.stock_pool], ['Weight_' + self.strategy_data.stock_pool]) pa_benchmark_weight = pa_benchmark_weight[ 'Weight_' + self.strategy_data.stock_pool] elif do_active_pa and self.strategy_data.stock_pool == 'all': temp_weight = data.read_data(['Weight_zz500'], ['Weight_zz500']) pa_benchmark_weight = temp_weight['Weight_zz500'] # 注意bb obj进行了一份深拷贝,这是因为在业绩归因的计算中,会根据不同的股票池丢弃数据,导致数据不全,因此不能传引用 bkt_obj.get_performance_attribution( outside_bb=bb_obj, benchmark_weight=pa_benchmark_weight, discard_factor=discard_factor, show_warning=False, foldername=stock_pool, pdfs=self.pdfs, is_real_world=False, real_world_type=2, enable_reading_pa_return=False) ################################################################################################### # 第六部分为, 1. 根据回归算单因子的纯因子组合收益率 # 2. 计算单因子的ic序列 # 3. 单因子选股策略的n分位图 # 4. 画单因子策略n分位图的long-short图 # 画单因子组合收益率 self.get_factor_return(weights=np.sqrt( self.strategy_data.stock_price.ix['FreeMarketValue']), holding_freq='w', direction=direction, start=bkt_start, end=bkt_end) # 画ic的走势图 self.get_factor_ic(direction=direction, holding_freq='w', start=bkt_start, end=bkt_end) # 画分位数图和long short图 self.plot_qgroup(bkt_obj, 3, direction=direction, value=1, weight=1) ################################################################################################### # 第七部分, 最后的收尾工作 self.pdfs.close()
# learning_rate=0.003, # n_iter=100) mlp_clf = mlp.Classifier( layers=[ mlp.Layer("Sigmoid", units=5), mlp.Layer("Softmax", units=3)], learning_rule="sgd", learning_rate=0.003, n_iter=150) # auto_encoder.fit(X.values) # auto_encoder.transfer(mlp_clf) mlp_clf.fit(X.values, y.values) pnl_history, order_history = backtest(testing_quotes, testing_trades, nn_strategy, transaction_costs=0.005, slippage_rate=0.25, delay_fill=True, nn_clf=mlp_clf) fig, axes = plt.subplots(nrows=4) axes[0].plot(quotes['DATE_TIME'].values, quotes['price'].values) for hl in hls: axes[0].plot(quotes['DATE_TIME'].values, quotes['EMA_{}'.format(hl)].values) long_orders = filter(lambda x: x[2] > 0, order_history) short_orders = filter(lambda x: x[2] < 0, order_history) long_order_times = map(lambda x: x[0], long_orders) short_order_times = map(lambda x: x[0], short_orders) long_order_prices = map(lambda x: x[3], long_orders) short_order_prices = map(lambda x: x[3], short_orders)
import yfinance as yf import numpy as np import pandas as pd import datetime from dataSource import data_source from trade_Robot import trade_Robot from wallet import wallet from backtest import backtest from strategy_01 import strategy_01 st = strategy_01() m = backtest("TSLA", 1000000, st, '2021-03-01', datetime.date.today()) m.execute()