def get_weights(self): code_list = list_jq2wind(self.code_list) code_weights = {} w.start() weight_data = np.array( w.wss(code_list, "mkt_cap_float", "unit=1;tradeDate=" + self.date + ";currencyType=").Data[0]) weight_data = weight_data / np.sum(weight_data) for i in range(len(code_list)): code = code_list[i] code_weights[list_wind2jq([code])[0]] = weight_data[i] return code_weights
def algo(context): date_now = context.now.strftime('%Y-%m-%d') date_previous = get_trading_date_from_now(date_now, -1, ql.Days) # 前一个交易日,用于获取因子数据的日期 if date_now not in trading_date_list: # 非调仓日 pass # 预留非调仓日的微调空间 else: # 调仓日执行算法 print(date_now + '日回测程序执行中...') try: code_list = list_gm2wind( list( get_history_constituents( INDEX, start_date=date_previous, end_date=date_previous)[0]['constituents'].keys())) except IndexError: code_list = w.wset("sectorconstituent", "date=" + date_previous + ";windcode=" + INDEX).Data[1] I = trading_date_list.index(date_now) trading_dates = trading_date_list[I - HISTORY_LENGTH:I + 1] data_dfs = [] for i in range(len(trading_dates) - 1): date_start = get_trading_date_from_now( trading_dates[i], -1, ql.Days) # 计算因子值的日子,买入前一日的因子值 date_end = get_trading_date_from_now(trading_dates[i + 1], -1, ql.Days) # 计算收益率到期的日子-收盘 factors_df = get_factor_from_wind(code_list, FACTOR_LIST, date_start) # 获取因子 return_df = get_return_from_wind(code_list, date_start, date_end) factors_df_and_return_df = pd.concat( [factors_df, return_df], axis=1).dropna() # 去掉因子或者回报有空缺值的样本 factors_df_and_return_df = sort_data( factors_df_and_return_df) # 使用排序数据作为输入 data_dfs.append(factors_df_and_return_df) factors_return_df = pd.concat(data_dfs, axis=0) # 获取的最终训练数据拼接,return为目标 # 根据data_df训练模型 model = OrdinaryLinearRegression() model.fit(factors_return_df) # 根据factor_date_previous选取股票 factor_date_previous_df = get_factor_from_wind(code_list, FACTOR_LIST, date_previous).dropna() sorted_codes = model.predict( factor_date_previous_df) # 获取预测收益率从小到大排序的股票列表 sorted_codes = list_wind2jq(sorted_codes) # 根据股票列表下单 stock_codes = sorted_codes[-STOCK_NUMBER:] stock_now = {} for stock_code in stock_codes: # 平均持仓持股 stock_now[stock_code] = 1. / STOCK_NUMBER stock_dict[date_now] = stock_now
def algo(context): date_now = context.now.strftime('%Y-%m-%d') date_previous = get_trading_date_from_now(date_now, -1, ql.Days) # 前一个交易日,用于获取因子数据的日期 if date_now not in trading_date_list: # 非调仓日 pass # 预留非调仓日的微调空间 else: # 调仓日执行算法 print(date_now+'日回测程序执行中...') # 根据指数获取股票候选池的代码 select_code_list = list_wind2jq(INCLUDED_INDEX) if len(select_code_list) > 0: # 有可选股票时选取合适的股票 stock_now = WEIGHTS(select_code_list, date_previous).get_weights() stock_dict[date_now] = stock_now else: stock_dict[date_now] = {}
def get_weights(self): code_list = list_jq2wind(self.code_list) w.start() return_value = np.array( w.wsd(code_list, "pct_chg", "ED-" + str(self.N - 1) + "TD", self.date, "").Data) return_value = return_value.transpose() return_value = pd.DataFrame(return_value, columns=code_list) optimizer = HRPOpt(return_value) hrp_portfolio = optimizer.hrp_portfolio() hrp_portfolio = dict( zip(list_wind2jq(list(hrp_portfolio.keys())), hrp_portfolio.values())) return hrp_portfolio
def algo(context): date_now = context.now.strftime('%Y-%m-%d') date_previous = get_trading_date_from_now(date_now, -1, ql.Days) # 前一个交易日,用于获取因子数据的日期 if date_now not in trading_date_list: # 非调仓日 pass # 预留非调仓日的微调空间 else: # 调仓日执行算法 print(date_now+'日回测程序执行中...') # 根据指数获取股票候选池的代码 code_list = SelectedStockPoolFromListV1(INCLUDED_INDEX, EXCLUDED_INDEX, date_previous).get_stock_pool() # 按照选股策略选股,与选股策略接口保持一致 strategy = STRATEGY(code_list, date_previous) select_code_list = list_wind2jq(strategy.select_code()) if len(select_code_list) > 0: # 有可选股票时选取合适的股票 stock_now = WEIGHTS(select_code_list, date_previous).get_weights() stock_dict[date_now] = stock_now else: stock_dict[date_now] = {}
def get_weights(self): code_list = list_jq2wind(self.code_list) SW1_code_list = [t[0] for t in SW1_INDEX] weight_value = self._calc_weights(SW1_code_list) # 提取行业权重 industry_list = w.wss(code_list, "indexcode_sw", "tradeDate="+self.date+";industryType=1").Data[0] weight_value_temp = [] for i in range(len(code_list)): industry_temp = industry_list[i] if industry_temp is None: # 个股无行业分类数据的处理 weight_value_temp.append(0.0) else: industry_index = SW1_code_list.index(industry_temp) weight_value_temp.append(weight_value[industry_index]) weight_value_temp = np.array(weight_value_temp) weight_value_temp = weight_value_temp / np.sum(weight_value_temp) # 权重归一化 code_weights = dict([[list_wind2jq([code_list[i]])[0], weight_value_temp[i]] for i in range(len(code_list))]) return code_weights
def algo(context): date_now = context.now.strftime('%Y-%m-%d') date_previous = get_trading_date_from_now(date_now, -1, ql.Days) # 前一个交易日,用于获取因子数据的日期 select_time_value = select_time_model[date_now] # 择时信号计算 select_time_dict[date_now] = select_time_value print(date_now + ('日回测程序执行中...,择时值:%.2f' % select_time_value)) if date_now not in trading_date_list: # 非调仓日 pass else: # 调仓日执行算法 # 根据指数获取股票候选池的代码 code_list = SelectedStockPoolFromListV1( INCLUDED_INDEX, EXCLUDED_INDEX, date_previous).get_stock_pool() strategy = STRATEGY(code_list, date_previous, 0.9) select_code_list = list_wind2jq(strategy.select_code()) if len(select_code_list) > 0: # 有可选股票时选取合适的股票 stock_now = WEIGHTS(select_code_list, date_previous).get_weights() else: stock_dict[date_now] = {}
def algo(context): date_now = context.now.strftime('%Y-%m-%d') print(date_now + '日回测程序执行中...') if date_now not in context.trading_date_list: # 非调仓日 pass # 预留非调仓日的微调空间 else: # 调仓日执行算法 date_previous = get_trading_date_from_now( date_now, -1, ql.Days) # 前一个交易日,用于获取因子数据的日期 code_list = SelectedStockPoolFromListExcluded( context.INCLUDED_INDEX, context.EXCLUDED_INDEX, date_previous).get_stock_pool() factor = context.FACTOR(date_previous, code_list) # 读取单因子的代码 df = factor.get_factor().dropna() quantiles = df.quantile(context.QUANTILE).values # 取对应的分位数值 stock_codes = list( df[(df[factor.factor_name] >= quantiles[0][0]) & (df[factor.factor_name] < quantiles[1][0])].index.values) stock_codes = list_wind2jq(stock_codes) # 仓位配置前转换为聚宽代码 stock_now = context.WEIGHTS_FUNCTION(stock_codes, date_previous).get_weights() stock_dict[date_now] = stock_now
def algo(context): global position_now, position_target date_now = context.now.strftime('%Y-%m-%d') date_previous = get_trading_date_from_now(date_now, -1, ql.Days) # 前一个交易日,用于获取因子数据的日期 select_time_value = select_time_model[date_now] # 择时信号计算 if date_now not in trading_date_list: # 非调仓日 pass else: # 调仓日执行算法,更新position_target position_now = False # 虚拟上,调仓日需要提前清仓 stock_dict[date_now] = {} # 根据指数获取股票候选池的代码 all_code_set = set() for index in INDEX: code_set = set( w.wset("sectorconstituent", "date=" + date_previous + ";windcode=" + index).Data[1]) all_code_set = all_code_set | code_set code_list = list(all_code_set) # 股票候选池 strategy = STRATEGY(code_list, date_previous, 0.9) select_code_list = list_wind2jq(strategy.select_code()) if len(select_code_list) > 0: # 有可选股票时记录下可选股票 stock_now = WEIGHTS(select_code_list, date_previous).get_weights() position_target = stock_now else: position_target = {} # 择时判定 if select_time_value >= 0 and not position_now and position_target != {}: # LLT择时信号为正,空仓且有目标持仓状态 stock_dict[date_now] = position_target position_now = True elif select_time_value < 0 and position_now and position_target != {}: # LLT择时信号为负且持仓状态: stock_dict[date_now] = {} position_now = False # 打印择时信号和仓位配置信息 print(date_now + ('日回测程序执行中...,择时值:%.2f' % select_time_value)) print(date_now + '日回测程序执行中...,选股:') print(position_target)
def get_weights(self): code_list = list_jq2wind(self.code_list) code_weights = {} return_value = self._get_return(code_list) def optimization_target(weight_temp): weight_temp = weight_temp[:, np.newaxis] portfolio_return_value = np.matmul(weight_temp.transpose(), return_value)[0, :] # 组合的投资回报序列 mean = np.mean(portfolio_return_value) var = np.var(portfolio_return_value) skew = scipy.stats.skew(portfolio_return_value) kurtosis = scipy.stats.kurtosis(portfolio_return_value) loss = self.w2 * var + self.w3 * skew + self.w4 * kurtosis # 对方差、偏度、丰度进行优化,期望值最小越好 return loss def constraint(weight_temp): return np.sum(weight_temp) - 1.0 n = len(self.code_list) # 资产个数 x_0 = np.ones((n, )) * 1.0 / n bounds = n * ((0.0, None), ) # 权重非负约束条件 res = scipy.optimize.minimize(optimization_target, x_0, method='SLSQP', bounds=bounds, constraints={ 'type': 'eq', 'fun': constraint }) # print(res) if res.success: # 优化成功 x = res.x else: # 优化失败,用等权 x = x_0 for i in range(len(code_list)): code = code_list[i] code_weights[list_wind2jq([code])[0]] = x[i] return code_weights
def get_weights(self): code_list = list_jq2wind(self.code_list) stock_ZX1_industry_code_list = w.wss( code_list, "indexcode_citic", "industryType=1;tradeDate=" + self.date).Data[0] ZX1_industry_code_list = list(set(stock_ZX1_industry_code_list)) weight_value = self._calc_weights(list( set(ZX1_industry_code_list))) # 计算股票涉及到的行业权重 # industry_list = w.wss(code_list, "indexcode_sw", "tradeDate="+self.date+";industryType=1").Data[0] weight_value_temp = [] for i in range(len(code_list)): industry_temp = stock_ZX1_industry_code_list[i] if industry_temp is None: # 个股无行业分类数据的处理 weight_value_temp.append(0.0) else: industry_index = ZX1_industry_code_list.index(industry_temp) weight_value_temp.append(weight_value[industry_index]) weight_value_temp = np.array(weight_value_temp) weight_value_temp = weight_value_temp / np.sum( weight_value_temp) # 权重归一化 code_weights = dict( [[list_wind2jq([code_list[i]])[0], weight_value_temp[i]] for i in range(len(code_list))]) return code_weights
risk_budget.append(value_ratio) risk_bounds.append([0.4, 0.85]) # 权重约束设置 elif value_code in [ '513050.SH', '513100.SH', '513500.SH', '518880.SH' ]: # 外盘黄金类 stock_pool.append(value_code) risk_budget.append(value_ratio) risk_bounds.append([0.0, 0.2]) # 权重约束设置 else: # 国内股票类 stock_pool.append(value_code) risk_budget.append(value_ratio) risk_bounds.append([0.0, 1.0]) # 权重约束设置 S_result.append([stock_pool, risk_budget, np.array(risk_bounds)]) # 策略0部分 stock_pool_0 = list_wind2jq(S_result[0][0]) risk_budget_0 = S_result[0][1] risk_bounds_0 = S_result[0][2] stock_weights_0 = 风险预算组合_模块求解基本版_带约束(stock_pool_0, DATE, risk_budget=risk_budget_0, bounds=risk_bounds_0).get_weights() # 加入信用债品种,对国债配置比例进行修正 stock_weights_0 = adjust_weights(stock_weights_0, BOND_ADJUST, STOCK_ADJUST) # 输出文字信息 string_output_0 = '策略0的风险预算权重为:\n' string_output_0 += str(dict(zip(stock_pool_0, risk_budget_0))) + '\n' string_output_0 += '策略0的选股结果(选股日为 ' + DATE + ' 收盘):\n' string_output_0 += str(stock_weights_0) + '\n' print(string_output_0)
stock_pool_bond = ['511010.SH'] risk_budget_bond = [1.0] # 候选目标[0.2, 0.8, 0.8] risk_bounds_bond = np.array([[0.0, 1.0]]) # 国内股票部分配置方案 stock_pool_stock = ['159949.SZ', '159928.SZ', '510050.SH', '510500.SH'] risk_budget_stock = [1.0, 1.0, 1.0, 1.0] # 总权重固定为4个单位 risk_bounds_stock = np.array([[0.0, 1.0]] * len(stock_pool_stock)) # 国际部分配置方案 stock_pool_global = ['513100.SH', '513500.SH', '518880.SH'] risk_budget_global = [0.75, 0.75, 0.8] # 在区间[0.75, 0.75, 0.8]-[1.0, 1.0, 1.0]之间灵活调整 risk_bounds_global = np.array([[0.0, 1.0]] * len(stock_pool_global)) # 合并为整体证券池 stock_pool = stock_pool_bond + stock_pool_stock + stock_pool_global risk_budget = risk_budget_bond + risk_budget_stock + risk_budget_global risk_bounds = np.concatenate([risk_bounds_bond, risk_bounds_stock, risk_bounds_global]) stock_pool = list_wind2jq(stock_pool) EXCLUDED_INDEX = [] # 剔除的股票代码 TRADING_DATES_LIST = ['15'] # 每月的调仓日期,非交易日寻找下一个最近的交易日 # 用于记录调仓信息的字典 stock_dict = {} # 根据回测阶段选取好调仓日期 trading_date_list = [] # 记录调仓日期的列表 def init(context): # 调仓日期获取 global trading_date_list trading_date_list = get_trading_date_list_by_day_monthly(BACKTEST_START_DATE, BACKTEST_END_DATE, TRADING_DATES_LIST) # 每天time_rule定时执行algo任务,time_rule处于09:00:00和15:00:00之间
views_vector.append(ws.cell(ws.nrows - 2, j).value) views_cov.append(ws.cell(ws.nrows - 1, j).value) views_matrix = np.array(views_matrix).transpose() views_vector = np.array(views_vector).reshape(-1, 1) views_cov = np.diag(np.array(views_cov)**2) return views_matrix, views_vector, views_cov if __name__ == '__main__': # 输入数据 date = '2019-11-04' file_path = '投资示例.xlsx' # 数据整理 code_list = 品种获取(file_path) views_matrix, views_vector, views_cov = 观点信息获取(file_path) code_weights = WEIGHTS(list_wind2jq(code_list), date).get_weights() # 风险平价收益和历史数据估计协方差数据 rp_weights = [code_weights[code] for code in code_weights] return_cov = 方差风险_历史数据(code_list, date, 60).return_cov * 240 # 主观观点标准差与历史估计标准差的比较 views_variance = get_variance_of_views_from_weights_covariances( return_cov, views_matrix) views_std = np.sqrt(views_variance) print('观点的历史数据估计标准差为:') print(views_std) print('观点的主观判断标准差为:') print(np.sqrt(np.diag(views_cov))) # BL模型的参数设定 delta_value = 50.0
def equal_transfer(code_list, date): # 按照date日的参数等权调仓 stock_now = {} for code in code_list: stock_now[list_wind2jq([code])[0]] = 1. / len(code_list) return stock_now
# 国内债券部分配置方案 stock_pool_1_bond = ['511010.SH'] risk_budget_1_bond = [1.0] risk_bounds_1_bond = np.array([[0.4, 1.0]]) # 国内股票部分配置方案 stock_pool_1_stock = [ '159928.SZ', '159949.SZ', '510050.SH', '512660.SH', '512720.SH', '515000.SH' ] risk_budget_1_stock = [0.7, 0.7, 0.7, 0.5, 0.8, 0.6] # 总权重固定为4个单位 risk_bounds_1_stock = np.array([[0.0, 1.0]] * len(stock_pool_1_stock)) # 合并为整体证券池 stock_pool_1 = stock_pool_1_bond + stock_pool_1_stock risk_budget_1 = risk_budget_1_bond + risk_budget_1_stock risk_bounds_1 = np.concatenate([risk_bounds_1_bond, risk_bounds_1_stock]) stock_pool_1 = list_wind2jq(stock_pool_1) stock_weights_1 = 风险预算组合_模块求解基本版_带约束(stock_pool_1, date_1, risk_budget=risk_budget_1, bounds=risk_bounds_1).get_weights() # 加入信用债品种,对国债配置比例进行修正 stock_weights_1['160618.XSHE'] = 0.05 stock_weights_1['161713.XSHE'] = 0.03 stock_weights_1['161716.XSHE'] = 0.09 stock_weights_1['167501.XSHE'] = 0.05 stock_weights_1['511010.XSHG'] = stock_weights_1['511010.XSHG'] - 0.22 # 输出文字信息 string_output_1 = '策略一的风险预算权重为:\n' string_output_1 += str(dict(zip(stock_pool_1, risk_budget_1))) + '\n' string_output_1 += '策略一的选股结果(选股日为 ' + date_1 + ' 收盘):\n' string_output_1 += str(stock_weights_1) + '\n'
def algo(context): global position_now, position_target date_now = context.now.strftime('%Y-%m-%d') date_previous = get_trading_date_from_now(date_now, -1, ql.Days) # 前一个交易日,用于获取因子数据的日期 select_time_value = select_time_model[date_now] # 择时信号计算 print(date_now + ('日回测程序执行中...,择时值:%.2f' % select_time_value)) if date_now not in trading_date_list: # 非调仓日 pass # 预留非调仓日的微调空间 else: # 调仓日执行算法 position_now = False # 虚拟上,调仓日需要提前清仓 # 根据指数获取股票候选池的代码 code_list = SelectedStockPoolFromListV1( INCLUDED_INDEX, EXCLUDED_INDEX, date_previous).get_stock_pool() I = trading_date_list.index(date_now) trading_dates = trading_date_list[I - HISTORY_LENGTH:I + 1] # 提取训练数据并训练模型 data_dfs = [] for i in range(len(trading_dates) - 1): date_start = get_trading_date_from_now( trading_dates[i], -1, ql.Days) # 计算因子值的日子,买入前一日的因子值 date_end = get_trading_date_from_now(trading_dates[i + 1], -1, ql.Days) # 计算收益率到期的日子-收盘 # 提取因子和收益数据 factors_df = get_factor_from_wind(code_list, FACTOR_LIST, date_start) # 获取因子 return_df = get_return_from_wind(code_list, date_start, date_end) factors_df_and_return_df = pd.concat( [factors_df, return_df], axis=1).dropna() # 去掉因子或者回报有空缺值的样本 factors_df_and_return_df = factor_and_return_process( factors_df_and_return_df) # 对因子和回报进行预处理# 使用排序数据作为输入 data_dfs.append(factors_df_and_return_df) factors_return_df = pd.concat(data_dfs, axis=0) # 获取的最终训练数据拼接,return为目标 # 根据data_df训练模型 model = OrdinaryLinearRegression(select_number=SELECT_NUMBER) model.fit(factors_return_df) # 根据factor_date_previous选取股票,使用模型 factor_date_previous_df = get_factor_from_wind(code_list, FACTOR_LIST, date_previous).dropna() factor_date_previous_df = factor_process( factor_date_previous_df) # 对因子进行预处理 select_code_list = model.predict( factor_date_previous_df) # 返回选取的股票代码,Wind格式 # 行业轮动部分 sw1_industry = get_SW1_industry(date_now, select_code_list) industry_wm_result = industry_wheel_movement[date_now] select_code_list = [ stock for stock in select_code_list if sw1_industry[stock] is not None and industry_wm_result[sw1_industry[stock]] == 1 ] # 忽略无行业信息的股票并根据行业择时信号选择候选股票 # 转化为聚宽代码格式 select_code_list = list_wind2jq(select_code_list) # 根据股票列表下单 if len(select_code_list) > 0: # 有可选股票时记录下可选股票 stock_now = WEIGHTS(select_code_list, date_previous).get_weights() position_target = stock_now else: position_target = {} # 择时判定 if select_time_value >= 0 and not position_now and position_target != {}: # LLT择时信号为正,空仓且有目标持仓状态 stock_dict[date_now] = position_target position_now = True elif select_time_value < 0 and position_now and position_target != {}: # LLT择时信号为负且持仓状态: stock_dict[date_now] = {} position_now = False