def sample_412(): """ 4.1.2 索引行列序列 :return: """ print('xrange:', xrange(stock_day_change.shape[0])) # 股票0 -> 股票stock_day_change.shape[0] stock_symbols = ['股票 1 ' + str(x) for x in xrange(stock_day_change.shape[0])] # 通过构造直接设置index参数,head(2)就显示两行,表4-2所示 print('pd.DataFrame(stock_day_change, index=stock_symbols).head(2):\n', pd.DataFrame(stock_day_change, index=stock_symbols).head(2)) # 从2017-1-1向上时间递进,单位freq='1d'即1天 days = pd.date_range('2017-1-1', periods=stock_day_change.shape[1], freq='1d') print('days:', days) # 股票0 -> 股票stock_day_change.shape[0] stock_symbols = ['股票 ' + str(x) for x in xrange(stock_day_change.shape[0])] # 分别设置index和columns df = pd.DataFrame(stock_day_change, index=stock_symbols, columns=days) # 表4-3所示 print('df.head(2):\n', df.head(2))
def sample_415(): """ 4.1.5 重采样数据 :return """ days = pd.date_range('2017-1-1', periods=stock_day_change.shape[1], freq='1d') stock_symbols = ['股票 ' + str(x) for x in xrange(stock_day_change.shape[0])] df = pd.DataFrame(stock_day_change, index=stock_symbols, columns=days) df = df.T df_stock0 = df['股票 0'] # 以5天为周期重采样(周k) df_stock0_5 = pd_resample(df_stock0.cumsum(), '5D', how='ohlc') # 以21天为周期重采样(月k), # noinspection PyUnusedLocal df_stock0_20 = pd_resample(df_stock0.cumsum(), '21D', how='ohlc') # 打印5天重采样,如下输出2017-01-01, 2017-01-06, 2017-01-11, 表4-6所示 print('df_stock0_5.head():\n', df_stock0_5.head()) from abupy import ABuMarketDrawing # 图4-2所示 ABuMarketDrawing.plot_candle_stick(df_stock0_5.index, df_stock0_5['open'].values, df_stock0_5['high'].values, df_stock0_5['low'].values, df_stock0_5['close'].values, np.random.random(len(df_stock0_5)), None, 'stock', day_sum=False, html_bk=False, save=False) print('type(df_stock0_5.open.values):', type(df_stock0_5['open'].values)) print('df_stock0_5.open.index:\n', df_stock0_5['open'].index) print('df_stock0_5.columns:\n', df_stock0_5.columns)
def gen_buy_change_list(): buy_change_list = [] for buy_change in xrange(-5, -16, -1): # 1. 除数或者被除数其中一个是float类型 buy_change = buy_change / 100.0 buy_change_list.append(buy_change) return buy_change_list
def gen_buy_change_list(): buy_change_list = [] # 下跌买入阀值从-0.05到-0.15,即从下跌5%到15% for buy_change in xrange(-5, -16, -1): buy_change = buy_change / 100 buy_change_list.append(buy_change) return buy_change_list
def sample_212(show=True): """ 2.1.2 字符串和容器 :return: """ show_func = print if show else lambda a: a price_str = '30.14, 29.58, 26.36, 32.56, 32.82' show_func('旧的price_str id= {}'.format(id(price_str))) price_str = price_str.replace(' ', '') show_func('新的price_str id= {}'.format(id(price_str))) show_func(price_str) # split以逗号分割字符串,返回数组price_array price_array = price_str.split(',') show_func(price_array) # price_array尾部append一个重复的32.82 price_array.append('32.82') show_func(price_array) show_func(set(price_array)) price_array.remove('32.82') show_func(price_array) date_array = [] date_base = 20170118 # 这里用for只是为了计数,无用的变量python建议使用'_'声明 for _ in xrange(0, len(price_array)): date_array.append(str(date_base)) # 本节只是简单示例,不考虑日期的进位 date_base += 1 show_func(date_array) date_base = 20170118 date_array = [str(date_base + ind) for ind, _ in enumerate(price_array)] show_func(date_array) stock_tuple_list = [(date, price) for date, price in zip(date_array, price_array)] # tuple访问使用索引 show_func('20170119日价格:{}'.format(stock_tuple_list[1][1])) show_func(stock_tuple_list) stock_namedtuple = namedtuple('stock', ('date', 'price')) stock_namedtuple_list = [ stock_namedtuple(date, price) for date, price in zip(date_array, price_array) ] # namedtuple访问使用price show_func('20170119日价格:{}'.format(stock_namedtuple_list[1].price)) show_func(stock_namedtuple_list) # 字典推导式:{key: value for in} stock_dict = {date: price for date, price in zip(date_array, price_array)} show_func('20170119日价格:{}'.format(stock_dict['20170119'])) show_func(stock_dict) show_func(stock_dict.keys()) stock_dict = OrderedDict( (date, price) for date, price in zip(date_array, price_array)) show_func(stock_dict.keys()) return stock_dict
def sample_243(): """ 2.4.3 使用编译库提高性能 :return: """ # 买入后持股天数放大寻找范围 1 - 503 天, 间隔1天 keep_stock_list = list(range(1, 504, 1)) # 下跌买入阀值寻找范围 -0.01 - -0.99 共99个 buy_change_list = [buy_change / 100.0 for buy_change in xrange(-1, -100, -1)] def do_single_task(): task_list = list(itertools.product(keep_stock_list, buy_change_list)) print('笛卡尔积参数集合总共结果为:{}个'.format(len(task_list))) for keep_stock_threshold, buy_change_threshold in task_list: calc(keep_stock_threshold, buy_change_threshold) import time start_time = time.time() do_single_task() end_time = time.time() print('{} cost {}s'.format(do_single_task.__name__, round(end_time - start_time, 3))) import numba as nb do_single_task_nb = nb.jit(do_single_task) start_time = time.time() do_single_task_nb() end_time = time.time() print('{} cost {}s'.format(do_single_task_nb.__name__, round(end_time - start_time, 3)))
def sample_625(): """ 6.2.5 非凸函数计算怎样度过一生最幸福 :return: """ import scipy.optimize as sco method = 'SLSQP' # 提供一个函数来规范参数,np.sum(weights) = 1 -> np.sum(weights) - 1 = 0 constraints = ({'type': 'eq', 'fun': lambda p_x: np.sum(p_x) - 1}) # 参数的范围选定 bounds = tuple((0, 0.9) for _ in xrange(3)) print('bounds:', bounds) def minimize_happiness_local(weights): # print(weights) return -my_life(weights)[1] # 初始化猜测最优参数,这里使用brute计算出的全局最优参数作为guess guess = [0.5, 0.2, 0.3] opt_local = sco.minimize(minimize_happiness_local, guess, method=method, bounds=bounds, constraints=constraints) print('opt_local:', opt_local)
def gen_buy_change_list(): buy_change_list = [] for buy_change in xrange(-5, -16, -1): # 1. 原始buy_change print(buy_change) buy_change = buy_change / 100 # 2. buy_change/100 print(buy_change) buy_change_list.append(buy_change) return buy_change_list
def sample_212(show=True): """ 2.1.2 字符串和容器 :return: """ show_func = print if show else lambda a: a price_str = '30.14, 29.58, 26.36, 32.56, 32.82' show_func('旧的price_str id= {}'.format(id(price_str))) price_str = price_str.replace(' ', '') show_func('新的price_str id= {}'.format(id(price_str))) show_func(price_str) # split以逗号分割字符串,返回数组price_array price_array = price_str.split(',') show_func(price_array) # price_array尾部append一个重复的32.82 price_array.append('32.82') show_func(price_array) show_func(set(price_array)) price_array.remove('32.82') show_func(price_array) date_array = [] date_base = 20170118 # 这里用for只是为了计数,无用的变量python建议使用'_'声明 for _ in xrange(0, len(price_array)): date_array.append(str(date_base)) # 本节只是简单示例,不考虑日期的进位 date_base += 1 show_func(date_array) date_base = 20170118 date_array = [str(date_base + ind) for ind, _ in enumerate(price_array)] show_func(date_array) stock_tuple_list = [(date, price) for date, price in zip(date_array, price_array)] # tuple访问使用索引 show_func('20170119日价格:{}'.format(stock_tuple_list[1][1])) show_func(stock_tuple_list) stock_namedtuple = namedtuple('stock', ('date', 'price')) stock_namedtuple_list = [stock_namedtuple(date, price) for date, price in zip(date_array, price_array)] # namedtuple访问使用price show_func('20170119日价格:{}'.format(stock_namedtuple_list[1].price)) show_func(stock_namedtuple_list) # 字典推导式:{key: value for in} stock_dict = {date: price for date, price in zip(date_array, price_array)} show_func('20170119日价格:{}'.format(stock_dict['20170119'])) show_func(stock_dict) show_func(stock_dict.keys()) stock_dict = OrderedDict((date, price) for date, price in zip(date_array, price_array)) show_func(stock_dict.keys()) return stock_dict
def gen_buy_change_list(): buy_change_list = [] for buy_change in xrange(-5, -16, -1): # 只针对循环执行到buy_change == -10,中断开始调试 if buy_change == -10: # 打断点,通过set_trace pdb.set_trace() buy_change = buy_change / 100 buy_change_list.append(buy_change) # 故意向外抛出异常 raise RuntimeError('debug for pdb')
def sample_412(): """ 4.1.2 索引行列序列 :return: """ # 股票0 -> 股票stock_day_change.shape[0] stock_symbols = ['股票 ' + str(x) for x in xrange(stock_day_change.shape[0])] # 通过构造直接设置index参数,head(2)就显示两行,表4-2所示 print('pd.DataFrame(stock_day_change, index=stock_symbols).head(2):\n', pd.DataFrame(stock_day_change, index=stock_symbols).head(2)) # 从2017-1-1向上时间递进,单位freq='1d'即1天 days = pd.date_range('2017-1-1', periods=stock_day_change.shape[1], freq='1d') # 股票0 -> 股票stock_day_change.shape[0] stock_symbols = ['股票 ' + str(x) for x in xrange(stock_day_change.shape[0])] # 分别设置index和columns df = pd.DataFrame(stock_day_change, index=stock_symbols, columns=days) # 表4-3所示 print('df.head(2):\n', df.head(2))
def sample_242(): """ 2.4.2 多进程 vs 多线程 :return: """ # range集合:买入后持股天数从2天-30天,间隔两天 keep_stock_list = list(range(2, 30, 2)) print('持股天数参数组:{}'.format(keep_stock_list)) # 下跌买入阀值从-0.05到-0.15,即从下跌5%到15% buy_change_list = [ buy_change / 100.0 for buy_change in xrange(-1, -100, -1) ] print('下跌阀值参数组:{}'.format(buy_change_list)) result = [] # 回调函数,通过add_done_callback任务完成后调用 def when_done(r): # when_done在主进程中运行 result.append(r.result()) """ with class_a() as a: 上下文管理器:稍后会具体讲解 """ with ProcessPoolExecutor() as pool: for keep_stock_threshold, buy_change_threshold in \ itertools.product(keep_stock_list, buy_change_list): """ submit提交任务:使用calc函数和的参数通过submit提交到独立进程 提交的任务必须是简单函数,进程并行不支持类方法、闭包等 函数参数和返回值必须兼容pickle序列化,进程间的通信需要 """ future_result = pool.submit(calc, keep_stock_threshold, buy_change_threshold) # 当进程完成任务即calc运行结束后的回调函数 future_result.add_done_callback(when_done) print('Process sorted(result)[::-1][:10]:\n', sorted(result)[::-1][:10]) result = [] def when_done(r): result.append(r.result()) with ThreadPoolExecutor(max_workers=8) as pool: for keep_stock_threshold, buy_change_threshold in \ itertools.product(keep_stock_list, buy_change_list): future_result = pool.submit(calc, keep_stock_threshold, buy_change_threshold) future_result.add_done_callback(when_done) print('Thread sorted(result)[::-1][:10]:\n', sorted(result)[::-1][:10])
def sample_242(): """ 2.4.2 多进程 vs 多线程 :return: """ # range集合:买入后持股天数从2天-30天,间隔两天 keep_stock_list = list(range(2, 30, 2)) print('持股天数参数组:{}'.format(keep_stock_list)) # 下跌买入阀值从-0.05到-0.15,即从下跌5%到15% buy_change_list = [buy_change / 100.0 for buy_change in xrange(-1, -100, -1)] print('下跌阀值参数组:{}'.format(buy_change_list)) result = [] # 回调函数,通过add_done_callback任务完成后调用 def when_done(r): # when_done在主进程中运行 result.append(r.result()) """ with class_a() as a: 上下文管理器:稍后会具体讲解 """ with ProcessPoolExecutor() as pool: for keep_stock_threshold, buy_change_threshold in \ itertools.product(keep_stock_list, buy_change_list): """ submit提交任务:使用calc函数和的参数通过submit提交到独立进程 提交的任务必须是简单函数,进程并行不支持类方法、闭包等 函数参数和返回值必须兼容pickle序列化,进程间的通信需要 """ future_result = pool.submit(calc, keep_stock_threshold, buy_change_threshold) # 当进程完成任务即calc运行结束后的回调函数 future_result.add_done_callback(when_done) print('Process sorted(result)[::-1][:10]:\n', sorted(result)[::-1][:10]) result = [] def when_done(r): result.append(r.result()) with ThreadPoolExecutor(max_workers=8) as pool: for keep_stock_threshold, buy_change_threshold in \ itertools.product(keep_stock_list, buy_change_list): future_result = pool.submit(calc, keep_stock_threshold, buy_change_threshold) future_result.add_done_callback(when_done) print('Thread sorted(result)[::-1][:10]:\n', sorted(result)[::-1][:10])
def gen_buy_change_list(): # 会打印出来,因为info >= level=logging.INFO logging.info("gen_buy_change_list begin") buy_change_list = [] for buy_change in xrange(-5, -16, -1): # 不会打印出来,debug < level=logging.INFO logging.debug(buy_change) buy_change = buy_change / 100 # 不会打印出来,debug < level=logging.INFO logging.debug(buy_change) buy_change_list.append(buy_change) # 会打印出来,因为info >= level=logging.INFO logging.info("gen_buy_change_list end") return buy_change_list
def sample_413(): """ 4.1.3 金融时间序列 :return: """ days = pd.date_range('2017-1-1', periods=stock_day_change.shape[1], freq='1d') stock_symbols = ['股票 ' + str(x) for x in xrange(stock_day_change.shape[0])] df = pd.DataFrame(stock_day_change, index=stock_symbols, columns=days) # df做个转置 df = df.T # 表4-4所示 print('df.head():\n', df.head()) df_20 = pd_resample(df, '21D', how='mean') # 表4-5所示 print('df_20.head():\n', df_20.head())
def sample_414(): """ 4.1.4 Series构建及方法 :return """ days = pd.date_range('2017-1-1', periods=stock_day_change.shape[1], freq='1d') stock_symbols = ['股票 ' + str(x) for x in xrange(stock_day_change.shape[0])] df = pd.DataFrame(stock_day_change, index=stock_symbols, columns=days) df = df.T print('df.head():\n', df.head()) df_stock0 = df['股票 0'] # 打印df_stock0类型 print('type(df_stock0):', type(df_stock0)) # 打印出Series的前5行数据, 与DataFrame一致 print('df_stock0.head():\n', df_stock0.head()) df_stock0.cumsum().plot() plt.show()
def sample_241_2(): """ 2.4.1_2 笛卡尔积最优参数 :return: """ # range集合:买入后持股天数从2天-30天,间隔两天 keep_stock_list = list(range(2, 30, 2)) print('持股天数参数组:{}'.format(keep_stock_list)) # 下跌买入阀值从-0.05到-0.15,即从下跌5%到15% buy_change_list = [buy_change / 100.0 for buy_change in xrange(-5, -16, -1)] print('下跌阀值参数组:{}'.format(buy_change_list)) result = [] for keep_stock_threshold, buy_change_threshold in itertools.product( keep_stock_list, buy_change_list): # 使用calc计算参数对应的最终盈利,结果加入result序列 result.append(calc(keep_stock_threshold, buy_change_threshold)) print('笛卡尔积参数集合总共结果为:{}个'.format(len(result))) # [::-1]将整个排序结果反转,反转后盈亏收益从最高向低排序 # [:10]取出收益最高的前10个组合查看 print(sorted(result)[::-1][:10])
# In[11]: price_array.remove('32.82') price_array # In[12]: date_array = [] date_base = 20170118 # 这里用for只是为了计数,无用的变量python建议使用'_'声明 for _ in xrange(0, len(price_array)): # 本节只是简单示例,不考虑日期的进位 date_array.append(str(date_base)) date_base += 1 date_array # In[13]: date_array = [] date_base = 20170118 price_cnt = len(price_array) - 1 while price_cnt > 0: date_array.append(str(date_base)) date_base += 1
def sample_622(): """ 6.2.2 使用蒙特卡洛方法计算怎样度过一生最幸福 :return: """ living_day, happiness, wealth, fame = my_life([0.4, 0.3, 0.3]) print('活了{}年,幸福指数{}, 积累财富{}, 名望权力{}'.format( living_day, happiness, wealth, fame)) from abupy import AbuProgress progress = AbuProgress(2000, 0, label='my_life...') result = [] for pos, _ in enumerate(xrange(2000)): # 2000次随机权重分配 weights = np.random.random(3) weights /= np.sum(weights) # result中:tuple[0]权重weights,,tuple[1]my_life返回的结果 result.append((weights, my_life(weights))) progress.show(a_progress=pos + 1) # result中tuple[1]=my_life返回的结果, my_life[1]=幸福指数,so->x[1][1] sorted_scores = sorted(result, key=lambda p_x: p_x[1][1], reverse=True) # 将最优权重sorted_scores[0][0]代入my_life得到结果 living_day, happiness, wealth, fame = my_life(sorted_scores[0][0]) print('活了{}年,幸福指数{}, 积累财富{}, 名望权力{}'.format (living_day, happiness, wealth, fame)) print('人生最优权重:追求健康{:.3f},追求财富{:.3f},追求名望{:.3f}'.format( sorted_scores[0][0][0], sorted_scores[0][0][1], sorted_scores[0][0][2])) # noinspection PyUnresolvedReferences from mpl_toolkits.mplot3d import Axes3D """ result中: tuple[0]权重weights, tuple[1]my_life返回的结果 r[0][0]: 追求健康长寿快乐的权重 r[0][1]: 追求财富金钱的权重 r[0][2]: 追求名望权力的权重 r[1][1]: my_life[1]=幸福指数 """ result_show = np.array( [[r[0][0], r[0][1], r[0][2], r[1][1]] for r in result]) fig = plt.figure(figsize=(9, 6)) ax = fig.gca(projection='3d') ax.view_init(30, 60) """ x:追求健康长寿快乐的权重, y:追求财富金钱的权重 z:追求名望权力的权重, c:color 幸福指数, 颜色越深越幸福 """ ax.scatter3D(result_show[:, 0], result_show[:, 1], result_show[:, 2], c=result_show[:, 3], cmap='spring') ax.set_xlabel('health') ax.set_ylabel('stock') ax.set_zlabel('fame') plt.show() # 幸福指数 happiness_result = result_show[:, 3] # 使用qcut分10份 print('pd.qcut(happiness_result, 10).value_counts():\n', pd.qcut(happiness_result, 10).value_counts())
def sample_622(): """ 6.2.2 使用蒙特卡洛方法计算怎样度过一生最幸福 :return: """ living_day, happiness, wealth, fame = my_life([0.4, 0.3, 0.3]) print('活了{}年,幸福指数{}, 积累财富{}, 名望权力{}'.format( living_day, happiness, wealth, fame)) from abupy import AbuProgress progress = AbuProgress(2000, 0, label='my_life...') result = [] for pos, _ in enumerate(xrange(2000)): # 2000次随机权重分配 weights = np.random.random(3) weights /= np.sum(weights) # result中:tuple[0]权重weights,,tuple[1]my_life返回的结果 result.append((weights, my_life(weights))) progress.show(a_progress=pos + 1) # result中tuple[1]=my_life返回的结果, my_life[1]=幸福指数,so->x[1][1] sorted_scores = sorted(result, key=lambda p_x: p_x[1][1], reverse=True) # 将最优权重sorted_scores[0][0]代入my_life得到结果 living_day, happiness, wealth, fame = my_life(sorted_scores[0][0]) print('活了{}年,幸福指数{}, 积累财富{}, 名望权力{}'.format (living_day, happiness, wealth, fame)) print('人生最优权重:追求健康{:.3f},追求财富{:.3f},追求名望{:.3f}'.format( sorted_scores[0][0][0], sorted_scores[0][0][1], sorted_scores[0][0][2])) # noinspection PyUnresolvedReferences from mpl_toolkits.mplot3d import Axes3D """ result中: tuple[0]权重weights, tuple[1]my_life返回的结果 r[0][0]: 追求健康长寿快乐的权重 r[0][1]: 追求财富金钱的权重 r[0][2]: 追求名望权力的权重 r[1][1]: my_life[1]=幸福指数 """ result_show = np.array([[r[0][0], r[0][1], r[0][2], r[1][1]] for r in result]) fig = plt.figure(figsize=(9, 6)) ax = fig.gca(projection='3d') ax.view_init(30, 60) """ x:追求健康长寿快乐的权重, y:追求财富金钱的权重 z:追求名望权力的权重, c:color 幸福指数, 颜色越深越幸福 """ ax.scatter3D(result_show[:, 0], result_show[:, 1], result_show[:, 2], c=result_show[:, 3], cmap='spring') ax.set_xlabel('health') ax.set_ylabel('stock') ax.set_zlabel('fame') plt.show() # 幸福指数 happiness_result = result_show[:, 3] # 使用qcut分10份 print('pd.qcut(happiness_result, 10).value_counts():\n', pd.qcut(happiness_result, 10).value_counts())
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 # 测试,使用上一节使用的参数 calc(20, -0.08) # %% # range集合:买入后持股天数从2天-30天,间隔两天 keep_stock_list = list(range(2, 30, 2)) print('持股天数参数组:{}'.format(keep_stock_list)) # 下跌买入阀值从-0.05到-0.15,即从下跌5%到15% buy_change_list = [buy_change / 100.0 for buy_change in xrange(-5, -16, -1)] print('下跌阀值参数组:{}'.format(buy_change_list)) # %% result = [] for keep_stock_threshold, buy_change_threshold in itertools.product( keep_stock_list, buy_change_list): # 使用calc计算参数对应的最终盈利,结果加入result序列 result.append(calc(keep_stock_threshold, buy_change_threshold)) print('笛卡尔积参数集合总共结果为:{}个'.format(len(result))) # %% # [::-1]将整个排序结果反转,反转后盈亏收益从最高向低排序 # [:10]取出收益最高的前10个组合查看