def sample_233_2(): """ 2.3.3_2 静态类方法@classmethod与@staticmethod :return: """ # 两年的TSLA收盘数据 to list price_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).close.tolist() # 两年的TSLA收盘日期 to list,这里的写法不考虑效率,只做演示使用 date_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).date.tolist() trade_days = StockTradeDays(price_array, 0, date_array) trade_strategy2 = TradeStrategy2() trade_loop_back = TradeLoopBack(trade_days, trade_strategy2) trade_loop_back.execute_trade() print('回测策略2 总盈亏为:{}%'.format( reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100)) plt.plot(np.array(trade_loop_back.profit_array).cumsum()) plt.show() # 实例化一个新的TradeStrategy2类对象 trade_strategy2 = TradeStrategy2() # 修改为买入后持有股票20天,默认为10天 TradeStrategy2.set_keep_stock_threshold(20) # 修改股价下跌买入阀值为-0.08(下跌8%),默认为-0.10(下跌10%) TradeStrategy2.set_buy_change_threshold(-0.08) # 实例化新的回测对象trade_loop_back trade_loop_back = TradeLoopBack(trade_days, trade_strategy2) # 执行回测 trade_loop_back.execute_trade() print('回测策略2 总盈亏为:{}%'.format( reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100)) # 可视化回测结果 plt.plot(np.array(trade_loop_back.profit_array).cumsum()) plt.show()
def sample_233_2(): """ 2.3.3_2 静态类方法@classmethod与@staticmethod :return: """ # 两年的TSLA收盘数据 to list price_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).close.tolist() # 两年的TSLA收盘日期 to list,这里的写法不考虑效率,只做演示使用 date_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).date.tolist() trade_days = StockTradeDays(price_array, 0, date_array) trade_strategy2 = TradeStrategy2() trade_loop_back = TradeLoopBack(trade_days, trade_strategy2) trade_loop_back.execute_trade() print('回测策略2 总盈亏为:{}%'.format(reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100)) plt.plot(np.array(trade_loop_back.profit_array).cumsum()) plt.show() # 实例化一个新的TradeStrategy2类对象 trade_strategy2 = TradeStrategy2() # 修改为买入后持有股票20天,默认为10天 TradeStrategy2.set_keep_stock_threshold(20) # 修改股价下跌买入阀值为-0.08(下跌8%),默认为-0.10(下跌10%) TradeStrategy2.set_buy_change_threshold(-0.08) # 实例化新的回测对象trade_loop_back trade_loop_back = TradeLoopBack(trade_days, trade_strategy2) # 执行回测 trade_loop_back.execute_trade() print('回测策略2 总盈亏为:{}%'.format(reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100)) # 可视化回测结果 plt.plot(np.array(trade_loop_back.profit_array).cumsum()) plt.show()
def loopBack(ohlcv): dif, dea, bar = talib.MACD(ohlcv.close, fastperiod=12, slowperiod=26, signalperiod=9) macd = {'dif': dif, 'dea': dea, 'bar': bar} #找出交易日 bar2 = bar * bar.shift(1) the_day = np.where(bar2 < 0, bar2, 0) timeIndex = ohlcv.index trade_days = stc.StockTradeDays(ohlcv.close, timeIndex[0], timeIndex) trade_strategy1 = ts.TradeStrategy() trade_strategy1.ohlcv = ohlcv trade_loop_back = tlp.TradeLoopBack(trade_days, trade_strategy1) trade_loop_back.execute_trade() #买卖操作时间节点 pdays = pd.DataFrame(trade_loop_back.days_array, columns=('date', 'stock')) #除去第一个值 0-nan != 0 totalFee = 1 - np.power( 1 - fee, len(np.where((pdays.stock - pdays.shift(1).stock) != 0)[0]) - 1) print('总手续费:{}%'.format(totalFee)) profit = -99 if len(trade_loop_back.profit_array) > 0: profit = (reduce(lambda a, b: a + b, trade_loop_back.profit_array)) * 100 print('回测策略1 总盈亏为:{}%'.format(profit)) drawData(ohlcv, macd, trade_loop_back, pdays) return [totalFee, profit, ohlcv.shape[0]]
def __init_change(self): price_float_array = [float(price_str) for price_str in self.__price_array] # 通过将时间平移形成两个错开的收盘价序列,通过zip打包成为一个新的序列 # 每个元素为相邻的两个收盘价格 pp_array = [(price1, price2) for price1, price2 in zip(price_float_array[:-1], price_float_array[1:])] change_array = list(map(lambda pp: reduce(lambda a, b: round((b - a) / a, 3), pp), pp_array)) # list insert插入数据,将第一天的涨跌幅设置为0 change_array.insert(0, 0) return change_array
def __init_change(self): """ 从price_array生成change_array :return: """ price_float_array = [float(price_str) for price_str in self.__price_array] # 通过将时间平移形成两个错开的收盘价序列,通过zip打包成为一个新的序列 # 每个元素为相邻的两个收盘价格 pp_array = [(price1, price2) for price1, price2 in zip(price_float_array[:-1], price_float_array[1:])] change_array = list(map(lambda pp: reduce(lambda a, b: round((b - a) / a, 3), pp), pp_array)) # list insert插入数据,将第一天的涨跌幅设置为0 change_array.insert(0, 0) return change_array
def sample_232(): """ 2.3.2 继承和多态 :return: """ # 两年的TSLA收盘数据 to list price_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).close.tolist() # 两年的TSLA收盘日期 to list,这里的写法不考虑效率,只做演示使用 date_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).date.tolist() trade_days = StockTradeDays(price_array, 0, date_array) trade_loop_back = TradeLoopBack(trade_days, TradeStrategy1()) trade_loop_back.execute_trade() print('回测策略1 总盈亏为:{}%'.format(reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100)) plt.plot(np.array(trade_loop_back.profit_array).cumsum()) plt.show()
def loopBack(symbol, interval): buy = sell = 1 fee = 0.002 #TODO:获取相同时间区间内的数据 data = hb.fetch_ohlcv(symbol, interval) arr = np.array(data) ohlcv = pd.DataFrame(arr, columns=('time', 'open', 'highest', 'lowest', 'close', 'volume')) ohlcv = ohlcv.sort_index(by='time') timeIndex = pd.date_range(time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime(int(ohlcv.head(1).time) / 1000)), periods=ohlcv.shape[0], freq=(lambda x: x + 'in' if x[-1] == 'm' else x)(interval)) ohlcv.index = timeIndex dif, dea, bar = talib.MACD(ohlcv.close, fastperiod=12, slowperiod=26, signalperiod=9) #找出交易日 bar2 = bar * bar.shift(1) the_day = np.where(bar2 < 0, bar2, 0) trade_days = stc.StockTradeDays(ohlcv.close, timeIndex[0], timeIndex) trade_strategy1 = ts.TradeStrategy() trade_strategy1.ohlcv = ohlcv trade_loop_back = tlp.TradeLoopBack(trade_days, trade_strategy1) trade_loop_back.execute_trade() #买卖操作时间节点 pdays = pd.DataFrame(trade_loop_back.days_array, columns=('date', 'stock')) #除去第一个值 0-nan != 0 totalFee = 1 - np.power( 1 - fee, len(np.where((pdays.stock - pdays.shift(1).stock) != 0)[0]) - 1) #print(symbol, interval) # print('总手续费:{}%'.format(totalFee)) # print('回测策略1 总盈亏为:{}%'.format((reduce(lambda a, b: a + b, trade_loop_back.profit_array)) * 100)) profit = -99 if len(trade_loop_back.profit_array) > 0: profit = (reduce(lambda a, b: a + b, trade_loop_back.profit_array)) * 100 return totalFee, profit, ohlcv.shape[0]
def calc(keep_stock_threshold, buy_change_threshold): """ :param keep_stock_threshold: 持股天数 :param buy_change_threshold: 下跌买入阀值 :return: 盈亏情况,输入的持股天数, 输入的下跌买入阀值 """ # 实例化TradeStrategy2 trade_strategy2 = TradeStrategy2() # 通过类方法设置买入后持股天数 TradeStrategy2.set_keep_stock_threshold(keep_stock_threshold) # 通过类方法设置下跌买入阀值 TradeStrategy2.set_buy_change_threshold(buy_change_threshold) # 进行回测 trade_loop_back = TradeLoopBack(trade_days, trade_strategy2) trade_loop_back.execute_trade() # 计算回测结果的最终盈亏值profit profit = 0.0 if len(trade_loop_back.profit_array) == 0 else reduce(lambda a, b: a + b, trade_loop_back.profit_array) # 返回值profit和函数的两个输入参数 return profit, keep_stock_threshold, buy_change_threshold
def calc(keep_stock_threshold, buy_change_threshold): """ :param keep_stock_threshold: 持股天数 :param buy_change_threshold: 下跌买入阀值 :return: 盈亏情况,输入的持股天数, 输入的下跌买入阀值 """ # 实例化TradeStrategy2 trade_strategy2 = TradeStrategy2() # 通过类方法设置买入后持股天数 TradeStrategy2.set_keep_stock_threshold(keep_stock_threshold) # 通过类方法设置下跌买入阀值 TradeStrategy2.set_buy_change_threshold(buy_change_threshold) # 进行回测 trade_loop_back = TradeLoopBack(g_trade_days, trade_strategy2) trade_loop_back.execute_trade() # 计算回测结果的最终盈亏值profit profit = 0.0 if len(trade_loop_back.profit_array) == 0 else \ reduce(lambda a, b: a + b, trade_loop_back.profit_array) # 返回值profit和函数的两个输入参数 return profit, keep_stock_threshold, buy_change_threshold
def sample_233_1(): """ 2.3.3_1 property属性 :return: """ trade_strategy1 = TradeStrategy1() # 买入阀值从0.07上升到0.1 trade_strategy1.buy_change_threshold = 0.1 # 两年的TSLA收盘数据 to list price_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).close.tolist() # 两年的TSLA收盘日期 to list,这里的写法不考虑效率,只做演示使用 date_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).date.tolist() trade_days = StockTradeDays(price_array, 0, date_array) trade_loop_back = TradeLoopBack(trade_days, trade_strategy1) trade_loop_back.execute_trade() print('回测策略1 总盈亏为:{}%'.format(reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100)) # 可视化profit_array plt.plot(np.array(trade_loop_back.profit_array).cumsum()) plt.show()
for ind, day in enumerate(self.trade_days): """ 以时间驱动,完成交易回测 """ if self.trade_strategy.keep_stock_day > 0: # 如果有持有股票,加入交易盈亏结果序列 self.profit_array.append(day.change) # hasattr: 用来查询对象有没有实现某个方法 if hasattr(self.trade_strategy, 'buy_strategy'): # 买入策略执行 self.trade_strategy.buy_strategy(ind, day, self.trade_days) if hasattr(self.trade_strategy, 'sell_strategy'): # 卖出策略执行 self.trade_strategy.sell_strategy(ind, day, self.trade_days) price_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).close.tolist() # 两年的TSLA收盘日期 to list,这里的写法不考虑效率,只做演示使用 date_array = ABuSymbolPd.make_kl_df('TSLA', n_folds=2).date.tolist() date_base = 20170118 trade_days = StockTradeDays(price_array, date_base, date_array) trade_loop_back = TradeLoopBack(trade_days, TradeStrategy1()) trade_loop_back.execute_trade() print('TradeLoopBack Strategy 1 {}%'.format( reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100))
def sample_223(show=True): """ 2.2.3 高阶函数 :return: """ stock_dict = sample_212(show=False) show_func = print if show else lambda a: a # 将字符串的的价格通过列表推导式显示转换为float类型 # 由于stock_dict是OrderedDict所以才可以直接 # 使用stock_dict.values()获取有序日期的收盘价格 price_float_array = [float(price_str) for price_str in stock_dict.values()] # 通过将时间平移形成两个错开的收盘价序列,通过zip打包成为一个新的序列, # 通过[:-1]:从第0个到倒数第二个,[1:]:从第一个到最后一个 错开形成相邻 # 组成的序列每个元素为相邻的两个收盘价格 pp_array = [(price1, price2) for price1, price2 in zip( price_float_array[:-1], price_float_array[1:])] show_func(pp_array) # list for python3 change_array = list( map(lambda pp: reduce(lambda a, b: round((b - a) / a, 3), pp), pp_array)) # list insert插入数据,将第一天的涨跌幅设置为0 change_array.insert(0, 0) show_func(change_array) price_str = '30.14, 29.58, 26.36, 32.56, 32.82' price_str = price_str.replace(' ', '') price_array = price_str.split(',') date_base = 20170118 date_array = [str(date_base + ind) for ind, _ in enumerate(price_array)] # 使用namedtuple重新构建数据结构 stock_namedtuple = namedtuple('stock', ('date', 'price', 'change')) # 通过zip分别从date_array,price_array,change_array拿数据组成 # stock_namedtuple然后以date做为key组成OrderedDict stock_dict = OrderedDict( (date, stock_namedtuple(date, price, change)) for date, price, change in zip(date_array, price_array, change_array)) show_func(stock_dict) # list for python3 up_days = list(filter(lambda day: day.change > 0, stock_dict.values())) show_func(up_days) def filter_stock(stock_array_dict, want_up=True, want_calc_sum=False): if not isinstance(stock_array_dict, OrderedDict): raise TypeError('stock_array_dict must be OrderedDict!') # python中的三目表达式的写法 filter_func = (lambda p_day: p_day.change > 0) if want_up else ( lambda p_day: p_day.change < 0) # 使用filter_func做筛选函数 want_days = list(filter(filter_func, stock_array_dict.values())) if not want_calc_sum: return want_days # 需要计算涨跌幅和 change_sum = 0.0 for day in want_days: change_sum += day.change return change_sum # 全部使用默认参数 show_func('所有上涨的交易日:{}'.format(filter_stock(stock_dict))) # want_up=False show_func('所有下跌的交易日:{}'.format(filter_stock(stock_dict, want_up=False))) # 计算所有上涨的总会 show_func('所有上涨交易日的涨幅和:{}'.format( filter_stock(stock_dict, want_calc_sum=True))) # 计算所有下跌的总会 show_func('所有下跌交易日的跌幅和:{}'.format( filter_stock(stock_dict, want_up=False, want_calc_sum=True))) return stock_dict
# 将字符串的的价格通过列表推导式显示转换为float类型 # 由于stock_dict是OrderedDict所以才可以直接 # 使用stock_dict.values()获取有序日期的收盘价格 price_float_array = [float(price_str) for price_str in stock_dict.values()] # 通过将时间平移形成两个错开的收盘价序列,通过zip打包成为一个新的序列, # 通过[:-1]:从第0个到倒数第二个,[1:]:从第一个到最后一个 错开形成相邻 # 组成的序列每个元素为相邻的两个收盘价格 pp_array = [(price1, price2) for price1, price2 in zip(price_float_array[:-1], price_float_array[1:])] pp_array # In[26]: # list(map) 配合 six.moves.map for python3 change_array = list(map(lambda pp: reduce(lambda a, b: round((b - a) / a, 3), pp), pp_array)) # list insert插入数据,将第一天的涨跌幅设置为0 change_array.insert(0, 0) change_array # In[27]: # 使用namedtuple重新构建数据结构 stock_namedtuple = namedtuple('stock', ('date', 'price', 'change')) # 通过zip分别从date_array,price_array,change_array拿数据组成 # stock_namedtuple然后以date做为key组成OrderedDict stock_dict = OrderedDict((date, stock_namedtuple(date, price, change)) for date, price, change in zip(date_array, price_array, change_array)) stock_dict
def sample_223(show=True): """ 2.2.3 高阶函数 :return: """ stock_dict = sample_212(show=False) show_func = print if show else lambda a: a # 将字符串的的价格通过列表推导式显示转换为float类型 # 由于stock_dict是OrderedDict所以才可以直接 # 使用stock_dict.values()获取有序日期的收盘价格 price_float_array = [float(price_str) for price_str in stock_dict.values()] # 通过将时间平移形成两个错开的收盘价序列,通过zip打包成为一个新的序列, # 通过[:-1]:从第0个到倒数第二个,[1:]:从第一个到最后一个 错开形成相邻 # 组成的序列每个元素为相邻的两个收盘价格 pp_array = [(price1, price2) for price1, price2 in zip(price_float_array[:-1], price_float_array[1:])] show_func(pp_array) # list for python3 change_array = list(map(lambda pp: reduce(lambda a, b: round((b - a) / a, 3), pp), pp_array)) # list insert插入数据,将第一天的涨跌幅设置为0 change_array.insert(0, 0) show_func(change_array) price_str = '30.14, 29.58, 26.36, 32.56, 32.82' price_str = price_str.replace(' ', '') price_array = price_str.split(',') date_base = 20170118 date_array = [str(date_base + ind) for ind, _ in enumerate(price_array)] # 使用namedtuple重新构建数据结构 stock_namedtuple = namedtuple('stock', ('date', 'price', 'change')) # 通过zip分别从date_array,price_array,change_array拿数据组成 # stock_namedtuple然后以date做为key组成OrderedDict stock_dict = OrderedDict((date, stock_namedtuple(date, price, change)) for date, price, change in zip(date_array, price_array, change_array)) show_func(stock_dict) # list for python3 up_days = list(filter(lambda day: day.change > 0, stock_dict.values())) show_func(up_days) def filter_stock(stock_array_dict, want_up=True, want_calc_sum=False): if not isinstance(stock_array_dict, OrderedDict): raise TypeError('stock_array_dict must be OrderedDict!') # python中的三目表达式的写法 filter_func = (lambda p_day: p_day.change > 0) if want_up else (lambda p_day: p_day.change < 0) # 使用filter_func做筛选函数 want_days = list(filter(filter_func, stock_array_dict.values())) if not want_calc_sum: return want_days # 需要计算涨跌幅和 change_sum = 0.0 for day in want_days: change_sum += day.change return change_sum # 全部使用默认参数 show_func('所有上涨的交易日:{}'.format(filter_stock(stock_dict))) # want_up=False show_func('所有下跌的交易日:{}'.format(filter_stock(stock_dict, want_up=False))) # 计算所有上涨的总会 show_func('所有上涨交易日的涨幅和:{}'.format(filter_stock(stock_dict, want_calc_sum=True))) # 计算所有下跌的总会 show_func('所有下跌交易日的跌幅和:{}'.format(filter_stock(stock_dict, want_up=False, want_calc_sum=True))) return stock_dict