| | |
| | | import datetime |
| | | import json |
| | | import time |
| | | |
| | | import constant |
| | | from log_module import async_log_util |
| | | from log_module.log import logger_common, logger_Overall_market_strength_score, logger_debug |
| | | # import time |
| | | # 引入掘金API |
| | | # from gm.api import * |
| | | from strategy import basic_methods, kpl_api |
| | | from strategy import data_cache |
| | | |
| | |
| | | |
| | | # 获取logger实例 |
| | | logger = logger_common |
| | | |
| | | # ====================== |
| | | # 模拟数据生成(完整版) |
| | | # ====================== |
| | | # data = { |
| | | # 'total_stocks': 5000, # 全市场股票总数 |
| | | # 'limit_up': 120, # 涨停股数量 |
| | | # 'limit_down': 5, # 跌停股数量 |
| | | # 'advance_count': 2800, # 上涨家数 |
| | | # 'decline_count': 1500, # 下跌家数 |
| | | # 'high_retreat_count': 30, # 当日回撤超10%的个股数量 |
| | | # 'turnover': 1.2e12, # 当日成交额(元) |
| | | # 'turnover_prev_day': 1.0e12, # 前一日成交额 |
| | | # 'northbound_inflow': 8e9, # 北向资金净流入(元) |
| | | # 'max_northbound_30d': 15e9, # 近30日最大北向净流入 |
| | | # 'margin_buy': 8e10, # 融资买入额 |
| | | # 'sector_gains': [3.5, 2.8, 1.9, -0.5], # 前4大板块涨幅(%) |
| | | # 'max_continuous_boards': 7, # 最高连板数(如7连板) |
| | | # 'continuous_boards': [7, 5, 3, 2], # 连板梯队(各层级连板数量) |
| | | # } |
| | | # |
| | | # |
| | | # # ====================== |
| | | # # 因子计算与标准化处理 |
| | | # # ====================== |
| | | # def calculate_factors(data): |
| | | # factors = {} |
| | | # |
| | | # # === 新增核心因子 === |
| | | # # 1. 涨跌家数比(0-100分) |
| | | # if data['decline_count'] == 0: |
| | | # factors['advance_ratio'] = 100.0 |
| | | # else: |
| | | # factors['advance_ratio'] = min( |
| | | # (data['advance_count'] / data['decline_count']) * 50, # 比值1:2对应100分 |
| | | # 100.0 |
| | | # ) |
| | | # |
| | | # # 2. 涨停强度(标准化到0-100) |
| | | # factors['limit_strength'] = ( |
| | | # (data['limit_up'] - data['limit_down']) / data['total_stocks'] * 1000 # 放大差异 |
| | | # ) |
| | | # |
| | | # # 3. 大幅回撤比例(0-100分) |
| | | # factors['high_retreat_ratio'] = ( |
| | | # data['high_retreat_count'] / data['total_stocks'] * 1000 # 千分比更敏感 |
| | | # ) |
| | | # |
| | | # # 4. 连板高度与梯队(根据历史极值归一化) |
| | | # factors['max_continuous'] = ( |
| | | # data['max_continuous_boards'] / 10 * 100 # 假设历史最高10连板 |
| | | # ) |
| | | # factors['board_ladder'] = ( |
| | | # len(data['continuous_boards']) / 5 * 100 # 假设最多5个连板层级 |
| | | # ) |
| | | # |
| | | # # === 原有因子优化 === |
| | | # # 5. 量能变化(成交额增长率) |
| | | # turnover_growth = ( |
| | | # (data['turnover'] - data['turnover_prev_day']) / |
| | | # data['turnover_prev_day'] * 100 |
| | | # ) |
| | | # factors['liquidity'] = turnover_growth |
| | | # |
| | | # # 6. 板块强度(前3板块平均涨幅) |
| | | # top_sectors = sorted(data['sector_gains'], reverse=True)[:3] |
| | | # sector_avg = sum(top_sectors) / len(top_sectors) |
| | | # |
| | | # factors['sector_strength'] = ((sector_avg - (-5.0)) / (10.0 - (-5.0)) * 100) # 历史范围-5%~10% |
| | | # # 7. 北向资金强度 |
| | | # factors['northbound_ratio'] = (data['northbound_inflow'] / data['max_northbound_30d'] * 100) |
| | | # |
| | | # # 8. 融资买入占比 |
| | | # factors['margin_ratio'] = (data['margin_buy'] / data['turnover'] * 100) |
| | | # |
| | | # # # 强制所有因子在0-100范围内 |
| | | # for key in factors: |
| | | # factors[key] = max(0.0, min(factors[key], 100.0)) |
| | | # |
| | | # return factors |
| | | # |
| | | # |
| | | # # ====================== |
| | | # # 权重分配(总权重1.0) |
| | | # # ====================== |
| | | # def get_weights(): |
| | | # return { |
| | | # # 新增因子权重 |
| | | # 'advance_ratio': 0.15, # 涨跌家数比 |
| | | # 'limit_strength': 0.2, # 涨停强度 |
| | | # 'high_retreat_ratio': 0.1, # 大幅回撤 |
| | | # 'max_continuous': 0.1, # 连板高度 |
| | | # 'board_ladder': 0.05, # 连板梯队 |
| | | # # 原有因子权重 |
| | | # 'liquidity': 0.15, # 量能变化 |
| | | # 'sector_strength': 0.1, # 板块强度 |
| | | # 'northbound_ratio': 0.1, # 北向资金 |
| | | # 'margin_ratio': 0.05 # 融资买入 |
| | | # } |
| | | # |
| | | # |
| | | # # ====================== |
| | | # # 综合强度分数计算(含动态修正) |
| | | # # ====================== |
| | | # def composite_strength_score(data): |
| | | # factors = calculate_factors(data) |
| | | # weights = get_weights() |
| | | # |
| | | # # 基础加权得分 |
| | | # score = sum(factors[key] * weights[key] for key in factors) |
| | | # |
| | | # # === 动态修正规则 === |
| | | # # 规则1:涨停数量超过100家时额外加分 |
| | | # if data['limit_up'] > 100: |
| | | # score += min((data['limit_up'] - 100) * 0.2, 10) # 最多加10分 |
| | | # |
| | | # # 规则2:连板梯队断裂时扣分(如最高板与次高板差距≥3) |
| | | # continuous_boards = sorted(data['continuous_boards'], reverse=True) |
| | | # if len(continuous_boards) >= 2 and (continuous_boards[0] - continuous_boards[1] >= 3): |
| | | # score -= 15 # 梯队断裂惩罚 |
| | | # |
| | | # # 规则3:北向资金与涨跌家数背离时调整 |
| | | # if (factors['northbound_ratio'] > 50) and (factors['advance_ratio'] < 40): |
| | | # score *= 0.9 # 权重股拉升导致的虚假繁荣 |
| | | # |
| | | # return max(0.0, min(score, 100.0)) |
| | | |
| | | |
| | | # ====================== |
| | | # 执行计算与结果输出 |
| | | # ====================== |
| | | # final_score = composite_strength_score(data) |
| | | # print("=== 综合强度分数 ===") |
| | | # print(f"当前得分: {final_score:.1f}/100") |
| | | # |
| | | # # 输出因子贡献度分析 |
| | | # factors = calculate_factors(data) |
| | | # weights = get_weights() |
| | | # print("\n=== 因子贡献度明细 ===") |
| | | # for key in factors: |
| | | # print(f"{key:20s}: {factors[key]:5.1f} × {weights[key]:.0%} = {factors[key] * weights[key]:5.1f}") |
| | | |
| | | ''' 代码输出示例: |
| | | === 综合强度分数 === |
| | | 当前得分: 78.4/100 |
| | | |
| | | === 因子贡献度明细 === |
| | | advance_ratio : 93.3 × 15% = 14.0 |
| | | limit_strength : 23.0 × 20% = 4.6 |
| | | high_retreat_ratio : 6.0 × 10% = 0.6 |
| | | max_continuous : 70.0 × 10% = 7.0 |
| | | board_ladder : 80.0 × 5% = 4.0 |
| | | liquidity : 20.0 × 15% = 3.0 |
| | | sector_strength : 60.0 × 10% = 6.0 |
| | | northbound_ratio : 53.3 × 10% = 5.3 |
| | | margin_ratio : 10.0 × 5% = 0.5 |
| | | ''' |
| | | |
| | | |
| | | # 指数行情策略函数 |
| | |
| | | 'TSXV': {} |
| | | } |
| | | if current_info is not None and len_current_info > 0: |
| | | # print(f"current_info------------{current_info}") |
| | | # 上证指数数据 |
| | | Shanghai_index_data = current_info.get('000001') |
| | | Shanghai_index = Shanghai_index_data[0] # 上证指数 |
| | | Shanghai_index_volume = round(Shanghai_index_data[1]/100000000, 2) # 上证指数 当日当时成交量 |
| | | Shanghai_index_turnover = round(Shanghai_index_data[2]/100000000, 2) # 上证指数 当日当时成交额度 |
| | | Shanghai_Yesterday_closing_index = round(Shanghai_index_data[3], 2) # 上证指数 昨日收盘指数 |
| | | logger.info(f"上证 指数:{Shanghai_index} 昨日收盘指数:{Shanghai_Yesterday_closing_index} 成交量:{Shanghai_index_volume}亿 手 成交额:{Shanghai_index_turnover}亿 元") |
| | | now_time_str = tool.get_now_time_str() |
| | | if data_cache.L1_DATA_START_TIME < now_time_str < data_cache.CLOSING_TIME: |
| | | # print(f"current_info------------{current_info}") |
| | | # 上证指数数据 |
| | | Shanghai_index_data = current_info.get('000001') |
| | | Shanghai_index = Shanghai_index_data[0] # 上证指数 |
| | | Shanghai_index_volume = round(Shanghai_index_data[1]/100000000, 2) # 上证指数 当日当时成交量 |
| | | Shanghai_index_turnover = round(Shanghai_index_data[2]/100000000, 2) # 上证指数 当日当时成交额度 |
| | | Shanghai_Yesterday_closing_index = round(Shanghai_index_data[3], 2) # 上证指数 昨日收盘指数 |
| | | logger.info(f"上证 指数:{Shanghai_index} 昨日收盘指数:{Shanghai_Yesterday_closing_index} 成交量:{Shanghai_index_volume}亿 手 成交额:{Shanghai_index_turnover}亿 元") |
| | | |
| | | # 深证指数数据 |
| | | Shenzhen_index_data = current_info.get('399001') |
| | | Shenzhen_index = Shenzhen_index_data[0] # 深证指数 |
| | | Shenzhen_index_volume = round(Shenzhen_index_data[1]/100000000, 2) # 深证指数 当日当时成交量 |
| | | Shenzhen_index_turnover = round(Shenzhen_index_data[2]/100000000, 2) # 深证指数 当日当时成交额度 |
| | | Shenzhen_Yesterday_closing_index = round(Shenzhen_index_data[3], 2) # 深证指数 昨日收盘指数 |
| | | logger.info(f"深证 指数:{Shenzhen_index} 昨日收盘指数:{Shenzhen_Yesterday_closing_index} 成交量:{Shenzhen_index_volume}亿 手 成交额:{Shenzhen_index_turnover}亿 元") |
| | | # 深证指数数据 |
| | | Shenzhen_index_data = current_info.get('399001') |
| | | Shenzhen_index = Shenzhen_index_data[0] # 深证指数 |
| | | Shenzhen_index_volume = round(Shenzhen_index_data[1]/100000000, 2) # 深证指数 当日当时成交量 |
| | | Shenzhen_index_turnover = round(Shenzhen_index_data[2]/100000000, 2) # 深证指数 当日当时成交额度 |
| | | Shenzhen_Yesterday_closing_index = round(Shenzhen_index_data[3], 2) # 深证指数 昨日收盘指数 |
| | | logger.info(f"深证 指数:{Shenzhen_index} 昨日收盘指数:{Shenzhen_Yesterday_closing_index} 成交量:{Shenzhen_index_volume}亿 手 成交额:{Shenzhen_index_turnover}亿 元") |
| | | |
| | | # 创业板指数数据 |
| | | TSXV_index_data = current_info.get('399006') |
| | | TSXV_index = TSXV_index_data[0] # 创业板指 |
| | | TSXV_index_volume = round(TSXV_index_data[1]/100000000, 2) # 创业板指 当日当时成交量 |
| | | TSXV_index_turnover = round(TSXV_index_data[2]/100000000, 2) # 创业板指 当日当时成交额度 |
| | | TSXV_Yesterday_closing_index = round(TSXV_index_data[3], 2) # 深证指数 昨日收盘指数 |
| | | logger.info(f"创业板 指数:{TSXV_index} 昨日收盘指数:{TSXV_Yesterday_closing_index} 成交量:{TSXV_index_volume}亿 手 成交额:{TSXV_index_turnover}亿 元") |
| | | # 创业板指数数据 |
| | | TSXV_index_data = current_info.get('399006') |
| | | TSXV_index = TSXV_index_data[0] # 创业板指 |
| | | TSXV_index_volume = round(TSXV_index_data[1]/100000000, 2) # 创业板指 当日当时成交量 |
| | | TSXV_index_turnover = round(TSXV_index_data[2]/100000000, 2) # 创业板指 当日当时成交额度 |
| | | TSXV_Yesterday_closing_index = round(TSXV_index_data[3], 2) # 深证指数 昨日收盘指数 |
| | | logger.info(f"创业板 指数:{TSXV_index} 昨日收盘指数:{TSXV_Yesterday_closing_index} 成交量:{TSXV_index_volume}亿 手 成交额:{TSXV_index_turnover}亿 元") |
| | | |
| | | # 调用涨幅公式计算对应的股票tick瞬时涨幅 |
| | | data_cache.Shanghai_tick_growth = basic_methods.tick_growth('000001', Shanghai_index) |
| | | data_cache.Shanghai_today_growth = basic_methods.intraday_growth(Shanghai_index, Shanghai_Yesterday_closing_index) |
| | | logger.info(f"上证指数 瞬时涨幅 ---- {round(data_cache.Shanghai_tick_growth, 4)}%") |
| | | logger.info(f"上证指数 当日涨幅 ==== {round(data_cache.Shanghai_today_growth, 4)}%") |
| | | # 调用涨幅公式计算对应的股票tick瞬时涨幅 |
| | | data_cache.Shenzhen_tick_growth = basic_methods.tick_growth('399001', Shanghai_index) |
| | | data_cache.Shenzhen_today_growth = basic_methods.intraday_growth(Shenzhen_index, Shenzhen_Yesterday_closing_index) |
| | | logger.info(f"深证指数 瞬时涨幅 ---- {round(data_cache.Shenzhen_tick_growth, 4)}%") |
| | | logger.info(f"深证指数 当日涨幅 ==== {round(data_cache.Shenzhen_today_growth, 4)}%") |
| | | # 调用涨幅公式计算对应的股票tick瞬时涨幅 |
| | | data_cache.TSXV_tick_growth = basic_methods.tick_growth('399006', Shanghai_index) |
| | | data_cache.TSXV_today_growth = basic_methods.intraday_growth(TSXV_index, TSXV_Yesterday_closing_index) |
| | | logger.info(f"创业板指 瞬时涨幅 ---- {round(data_cache.TSXV_tick_growth, 4)}%") |
| | | logger.info(f"创业板指 当日涨幅 ==== {round(data_cache.TSXV_today_growth, 4)}%") |
| | | # 调用涨幅公式计算对应的股票tick瞬时涨幅 |
| | | data_cache.Shanghai_tick_growth = basic_methods.tick_growth('000001', Shanghai_index) |
| | | data_cache.Shanghai_today_growth = basic_methods.intraday_growth(Shanghai_index, Shanghai_Yesterday_closing_index) |
| | | logger.info(f"上证指数 瞬时涨幅 ---- {round(data_cache.Shanghai_tick_growth, 4)}%") |
| | | logger.info(f"上证指数 当日涨幅 ==== {round(data_cache.Shanghai_today_growth, 4)}%") |
| | | # 调用涨幅公式计算对应的股票tick瞬时涨幅 |
| | | data_cache.Shenzhen_tick_growth = basic_methods.tick_growth('399001', Shanghai_index) |
| | | data_cache.Shenzhen_today_growth = basic_methods.intraday_growth(Shenzhen_index, Shenzhen_Yesterday_closing_index) |
| | | logger.info(f"深证指数 瞬时涨幅 ---- {round(data_cache.Shenzhen_tick_growth, 4)}%") |
| | | logger.info(f"深证指数 当日涨幅 ==== {round(data_cache.Shenzhen_today_growth, 4)}%") |
| | | # 调用涨幅公式计算对应的股票tick瞬时涨幅 |
| | | data_cache.TSXV_tick_growth = basic_methods.tick_growth('399006', Shanghai_index) |
| | | data_cache.TSXV_today_growth = basic_methods.intraday_growth(TSXV_index, TSXV_Yesterday_closing_index) |
| | | logger.info(f"创业板指 瞬时涨幅 ---- {round(data_cache.TSXV_tick_growth, 4)}%") |
| | | logger.info(f"创业板指 当日涨幅 ==== {round(data_cache.TSXV_today_growth, 4)}%") |
| | | |
| | | # 在集合竞价时更新一下 各个指数的开盘涨幅 |
| | | now_time = tool.get_now_time_str() |
| | | # 9:25:06 < now_time < 9:25:12 记录开盘指数 及 开盘涨幅 |
| | | if data_cache.LATER_OPEN_BIDDING_TIME < now_time < data_cache.AFTER_OPEN_BIDDING_TIME: |
| | | index_K_line['Shanghai']['Shanghai_open_index'] = Shanghai_index |
| | | index_K_line['Shenzhen']['Shenzhen_open_index'] = Shenzhen_index |
| | | index_K_line['TSXV']['TSXV_open_index'] = TSXV_index |
| | | data_cache.Shanghai_open_growth = data_cache.Shanghai_today_growth |
| | | data_cache.Shenzhen_open_growth = data_cache.Shenzhen_today_growth |
| | | data_cache.TSXV_open_growth = data_cache.TSXV_today_growth |
| | | # 在集合竞价时更新一下 各个指数的开盘涨幅 |
| | | now_time = tool.get_now_time_str() |
| | | # 9:25:06 < now_time < 9:25:12 记录开盘指数 及 开盘涨幅 |
| | | if data_cache.LATER_OPEN_BIDDING_TIME < now_time < data_cache.AFTER_OPEN_BIDDING_TIME: |
| | | index_K_line['Shanghai']['Shanghai_open_index'] = Shanghai_index |
| | | index_K_line['Shenzhen']['Shenzhen_open_index'] = Shenzhen_index |
| | | index_K_line['TSXV']['TSXV_open_index'] = TSXV_index |
| | | data_cache.Shanghai_open_growth = data_cache.Shanghai_today_growth |
| | | data_cache.Shenzhen_open_growth = data_cache.Shenzhen_today_growth |
| | | data_cache.TSXV_open_growth = data_cache.TSXV_today_growth |
| | | |
| | | # 15:00:00 < now_time < 15:01:00 记录收盘指数 |
| | | if data_cache.CLOSING_TIME < now_time < data_cache.AFTER_CLOSING_TIME: |
| | | index_K_line['Shanghai']['Shanghai_close_index'] = Shanghai_index |
| | | index_K_line['Shenzhen']['Shenzhen_close_index'] = Shenzhen_index |
| | | index_K_line['TSXV']['TSXV_close_index'] = TSXV_index |
| | | # 15:00:00 < now_time < 15:01:00 记录收盘指数 |
| | | if data_cache.CLOSING_TIME < now_time < data_cache.AFTER_CLOSING_TIME: |
| | | index_K_line['Shanghai']['Shanghai_close_index'] = Shanghai_index |
| | | index_K_line['Shenzhen']['Shenzhen_close_index'] = Shenzhen_index |
| | | index_K_line['TSXV']['TSXV_close_index'] = TSXV_index |
| | | |
| | | logger.info(f"上证指数 开盘涨幅 ==== {round(data_cache.Shanghai_open_growth, 4)}%") |
| | | logger.info(f"深证指数 开盘涨幅 ==== {round(data_cache.Shenzhen_open_growth, 4)}%") |
| | | logger.info(f"创业板指 开盘涨幅 ==== {round(data_cache.TSXV_open_growth, 4)}%") |
| | | logger.info(f"上证指数 开盘涨幅 ==== {round(data_cache.Shanghai_open_growth, 4)}%") |
| | | logger.info(f"深证指数 开盘涨幅 ==== {round(data_cache.Shenzhen_open_growth, 4)}%") |
| | | logger.info(f"创业板指 开盘涨幅 ==== {round(data_cache.TSXV_open_growth, 4)}%") |
| | | |
| | | |
| | | # 大盘指数趋势预期函数(用于对大盘开盘后短期内的趋势预测) |
| | |
| | | |
| | | |
| | | # 计算市场分布形态因子 函数 |
| | | def calculate_market_distribution_pattern_factor(data): |
| | | # ====================== 输入数据 ====================== |
| | | data = {'-1': '210', '-10': '4', '-2': '134', '-3': '71', '-4': '45', '-5': '18', '-6': '15', '-7': '7', '-8': '6', '-9': '2', '0': '83', '1': '650', '10': '41', '2': '1242', '3': '1182', '4': '784', '5': '334', '6': '139', '7': '77', '8': '46', '9': '16', 'DT': 5, 'SJDT': '1', 'SJZT': '17', 'STDT': '4', 'STZT': '2', 'SZJS': 4530, 'XDJS': 517, 'ZSZDFB': '1929,247,56,435,61,3,259,29,4,44,5,1,38,9,3,239,51,10,', 'ZT': 19, 'sign': '市场人气较好', 'szln': 1723817, 'qscln': 5291241, 's_zrcs': 2413498, 'q_zrcs': 6183792, 's_zrtj': 75543024, 'q_zrtj': 169960513} |
| | | |
| | | # ====================== 数据预处理 ====================== |
| | | def preprocess_data(data): |
| | | """ |
| | | 原生Python数据预处理 |
| | | 返回: |
| | | sorted_bins : 排序后的涨跌幅区间(整数列表) |
| | | sorted_counts : 对应区间的股票数量 |
| | | total : 总股票数 |
| | | pos_counts : 正涨跌区间的数量列表 |
| | | neg_counts : 负涨跌区间的数量列表 |
| | | """ |
| | | # 将字符串键转为整数并排序 |
| | | sorted_items = sorted(data.items(), key=lambda x: int(x[0])) |
| | | sorted_bins = [int(k) for k, v in sorted_items] |
| | | sorted_counts = [v for k, v in sorted_items] |
| | | 预处理原始数据: |
| | | 1. 转换所有数值字段为整数 |
| | | 2. 解析涨跌分布(ZSZDFB)为整数列表 |
| | | 3. 分离涨跌幅分布数据 |
| | | """ |
| | | processed = {} |
| | | |
| | | # 计算总股票数 |
| | | total = sum(sorted_counts) |
| | | |
| | | # 分离正负区间(排除0%) |
| | | pos_counts = [v for k, v in sorted_items if int(k) > 0] |
| | | neg_counts = [v for k, v in sorted_items if int(k) < 0] |
| | | |
| | | return sorted_bins, sorted_counts, total, pos_counts, neg_counts |
| | | |
| | | |
| | | # 执行预处理 |
| | | bins, counts, total, pos_counts, neg_counts = calculate_market_distribution_pattern_factor(data_cache.rise_and_fall_statistics_dirt) |
| | | |
| | | |
| | | # ====================== 因子计算模块 ====================== |
| | | class NativeFactorCalculator: |
| | | def __init__(self, bins, counts, total, pos_counts, neg_counts): |
| | | self.bins = bins |
| | | self.counts = counts |
| | | # todo total 会默认为0的情况 |
| | | if total != 0: |
| | | self.total = total |
| | | # 通用字段类型转换 |
| | | for key, value in data.items(): |
| | | if isinstance(value, str) and value.isdigit(): # 处理字符串数字 |
| | | processed[key] = int(value) |
| | | elif key == 'ZSZDFB': # 特殊处理涨跌分布 |
| | | # 过滤空值并转换为整数列表 |
| | | processed[key] = [int(x) for x in value.strip(',').split(',')] |
| | | else: |
| | | self.total = 1 |
| | | self.pos_counts = pos_counts |
| | | self.neg_counts = neg_counts |
| | | processed[key] = value # 保留原始类型 |
| | | |
| | | def calculate_bdr(self): |
| | | """原生涨跌比计算""" |
| | | sum_pos = sum(self.pos_counts) |
| | | sum_neg = sum(self.neg_counts) |
| | | return sum_pos / sum_neg if sum_neg != 0 else float('nan') |
| | | |
| | | def calculate_extreme_ratio(self): |
| | | """极端波动比例计算""" |
| | | extreme_total = 0 |
| | | for b, c in zip(self.bins, self.counts): |
| | | if b >= 5 or b <= -5: |
| | | extreme_total += c |
| | | return extreme_total / self.total |
| | | |
| | | def calculate_market_breadth(self): |
| | | """市场宽度因子计算""" |
| | | diff = sum(self.pos_counts) - sum(self.neg_counts) |
| | | return diff / self.total |
| | | |
| | | def _expand_distribution(self): |
| | | """将分箱数据展开为原始数据点(用于计算统计指标)""" |
| | | expanded = [] |
| | | for value, count in zip(self.bins, self.counts): |
| | | expanded.extend([value] * count) |
| | | return expanded |
| | | |
| | | def calculate_distribution_metrics(self): |
| | | """原生偏度与峰度计算""" |
| | | data = self._expand_distribution() |
| | | n = len(data) |
| | | if n < 2: |
| | | return (float('nan'), float('nan')) |
| | | |
| | | # 计算均值 |
| | | mean = sum(data) / n |
| | | |
| | | # 计算标准差 |
| | | variance = sum((x - mean) ** 2 for x in data) / (n - 1) |
| | | std_dev = variance ** 0.5 |
| | | |
| | | # 计算偏度 |
| | | skewness = (sum((x - mean) ** 3 for x in data) / n) / (std_dev ** 3) if std_dev != 0 else 0 |
| | | |
| | | # 计算峰度(Fisher定义,即正态分布峰度为0) |
| | | kurtosis = (sum((x - mean) ** 4 for x in data) / n) / (std_dev ** 4) - 3 if std_dev != 0 else 0 |
| | | |
| | | return (skewness, kurtosis) |
| | | # 分离涨跌幅分布数据(示例划分,具体区间需确认) |
| | | # 假设ZSZDFB对应从-10%到10%的18个区间分布(根据数据长度推测) |
| | | processed['price_distribution'] = { |
| | | 'bins': list(range(-10, 11)), # 生成-10到10的整数区间标识 |
| | | 'counts': processed['ZSZDFB'] |
| | | } |
| | | return processed |
| | | |
| | | |
| | | # 实例化并计算因子 |
| | | calculator = NativeFactorCalculator(bins, counts, total, pos_counts, neg_counts) |
| | | bdr = calculator.calculate_bdr() |
| | | extreme_ratio = calculator.calculate_extreme_ratio() |
| | | market_breadth = calculator.calculate_market_breadth() |
| | | skewness, kurtosis = calculator.calculate_distribution_metrics() |
| | | # data = preprocess_data(raw_data) |
| | | |
| | | |
| | | # ====================== 策略信号生成模块 ====================== |
| | | class NativeTradingStrategy: |
| | | def __init__(self, bdr_threshold=1.5, extreme_threshold=0.15): |
| | | self.bdr_threshold = bdr_threshold |
| | | self.extreme_threshold = extreme_threshold |
| | | # ====================== 核心因子计算 ====================== |
| | | def calculate_factors(data): |
| | | if data is not None: |
| | | zero = int(data.get('0')) |
| | | rise_one = int(data.get('1')) |
| | | rise_two = int(data.get('2')) |
| | | rise_three = int(data.get('3')) |
| | | rise_four = int(data.get('4')) |
| | | rise_five = int(data.get('5')) |
| | | rise_six = int(data.get('6')) |
| | | rise_seven = int(data.get('7')) |
| | | rise_eight = int(data.get('8')) |
| | | rise_nine = int(data.get('9')) |
| | | rise_ten = int(data.get('10')) |
| | | fall_one = int(data.get('-1')) |
| | | fall_two = int(data.get('-2')) |
| | | fall_three = int(data.get('-3')) |
| | | fall_four = int(data.get('-4')) |
| | | fall_five = int(data.get('-5')) |
| | | fall_six = int(data.get('-6')) |
| | | fall_seven = int(data.get('-7')) |
| | | fall_eight = int(data.get('-8')) |
| | | fall_nine = int(data.get('-9')) |
| | | fall_ten = int(data.get('-10')) |
| | | print(type(fall_ten)) |
| | | |
| | | def generate_signals(self, bdr, extreme_ratio, market_breadth, skewness): |
| | | """生成交易信号(与之前相同,保持策略逻辑)""" |
| | | signals = [] |
| | | """计算市场关键指标因子""" |
| | | factors = {} |
| | | # 总票数 |
| | | total_stocks = zero + rise_one + rise_two + rise_three + rise_four + rise_five + rise_six + rise_seven + rise_eight + rise_nine + rise_ten + fall_one + fall_two + fall_three + fall_four + fall_five + fall_six + fall_seven + fall_eight + fall_nine + fall_ten |
| | | print(f"total_stocks = {total_stocks}") |
| | | factors['total_stocks'] = total_stocks |
| | | # 涨跌统计(排除0%) |
| | | rise = rise_one + rise_two + rise_three + rise_four + rise_five + rise_six + rise_seven + rise_eight + rise_nine + rise_ten |
| | | fall = fall_one + fall_two + fall_three + fall_four + fall_five + fall_six + fall_seven + fall_eight + fall_nine + fall_ten |
| | | |
| | | # 信号1:基于涨跌比 |
| | | if bdr > self.bdr_threshold: |
| | | signals.append("多头趋势增强 - 加仓指数ETF") |
| | | elif bdr < 1 / self.bdr_threshold: |
| | | signals.append("空头趋势增强 - 减仓或反向操作") |
| | | else: |
| | | signals.append("趋势中性 - 保持当前仓位") |
| | | rise_dirt = { |
| | | 'rise_one': rise_one, |
| | | 'rise_two': rise_two, |
| | | 'rise_three': rise_three, |
| | | 'rise_four': rise_four, |
| | | 'rise_five': rise_five, |
| | | 'rise_six': rise_six, |
| | | 'rise_seven': rise_seven, |
| | | 'rise_eight': rise_eight, |
| | | 'rise_nine': rise_nine, |
| | | 'rise_ten': rise_ten, |
| | | } |
| | | fall_dirt = { |
| | | 'fall_one': fall_one, |
| | | 'fall_two': fall_two, |
| | | 'fall_three': fall_three, |
| | | 'fall_four': fall_four, |
| | | 'fall_five': fall_five, |
| | | 'fall_six': fall_six, |
| | | 'fall_seven': fall_seven, |
| | | 'fall_eight': fall_eight, |
| | | 'fall_nine': fall_nine, |
| | | 'fall_ten': fall_ten, |
| | | } |
| | | # 计算所有值的总和 |
| | | total_sum = sum(rise_dirt.values()) |
| | | # 计算每个键的值占总和的百分比 |
| | | percentages = {key: round((value / total_sum) * 100, 2) for key, value in rise_dirt.items()} |
| | | # 找到最大值对应的键 |
| | | max_key = max(rise_dirt, key=rise_dirt.get) |
| | | # 找到最小值对应的键 |
| | | min_key = min(rise_dirt, key=rise_dirt.get) |
| | | |
| | | # 信号2:极端波动 |
| | | if extreme_ratio > self.extreme_threshold: |
| | | signals.append("波动风险升高 - 启动对冲或降低杠杆") |
| | | else: |
| | | signals.append("波动正常 - 维持现有风险敞口") |
| | | # 涨跌比因子 --------------------------------------------------- |
| | | factors['rise_vs_fall'] = { |
| | | 'rise_vs_fall_ratio': rise / fall if fall > 0 else 0, # 涨跌比 |
| | | 'rise_gather_area': max_key, # 找到最大值 |
| | | 'rise_scattered_area': min_key, # 找到最小值 |
| | | 'percentages': percentages, # 找到最小值 |
| | | } |
| | | |
| | | # 信号3:市场宽度与偏度 |
| | | if market_breadth > 0.2 and skewness > 0.5: |
| | | signals.append("市场普涨且偏度正向 - 超配行业龙头股") |
| | | elif market_breadth < -0.2 and skewness < -0.5: |
| | | signals.append("市场普跌且偏度负向 - 低估值防御型配置") |
| | | return signals |
| | | # 资金流向因子 -------------------------------------------------- |
| | | factors['capital_flow'] = { |
| | | 'buy': data['q_zrtj'], # 买方资金净流入 |
| | | 'sell': data['s_zrtj'], # 卖方资金净流出 |
| | | 'net': data['q_zrtj'] - data['s_zrtj'] # 资金净流入 |
| | | } |
| | | |
| | | # 市场情绪因子 -------------------------------------------------- |
| | | factors['sentiment'] = { |
| | | 'zt_ratio': data['ZT'] / total_stocks, # 涨停占总比 |
| | | 'zt_vs_dt_ratio': data['ZT'] / data['DT'], # 涨停跌停比 |
| | | 'sign': 1 if '较好' in data['sign'] else 0, # 情绪标签量化 |
| | | 'rise_vs_all_stocks_ratio': data['SZJS'] / total_stocks, # 活跃股占比 |
| | | 'rise_vs_fall_ratio': data['SZJS'] / data['SZJS'], # 活跃股占比 |
| | | 'extreme_ratio': (data['ZT'] + data['DT']) / total_stocks, # 极端波动(涨停+跌停占总比) |
| | | } |
| | | return factors |
| | | |
| | | # 实例化策略并生成信号 |
| | | strategy = NativeTradingStrategy() |
| | | signals = strategy.generate_signals(bdr, extreme_ratio, market_breadth, skewness) |
| | | # |
| | | # # ====================== 策略信号生成 ====================== |
| | | def generate_signals(factors): |
| | | """生成多维度交易信号""" |
| | | signals = [] |
| | | # 信号1:趋势强度判断 |
| | | if factors['sentiment']['rise_vs_fall_ratio'] > 1.5: |
| | | signals.append("多头强势:涨跌比高于阈值1.5") |
| | | elif factors['sentiment']['rise_vs_fall_ratio'] < 0.67: |
| | | signals.append("空头强势:涨跌比低于阈值0.67") |
| | | |
| | | # 信号2:资金动能判断 |
| | | if factors['capital_flow']['net'] > 1e8: # 假设1亿为阈值 |
| | | signals.append("资金大幅净流入:关注主力进场") |
| | | elif factors['capital_flow']['net'] < -5e7: |
| | | signals.append("资金大幅净流出:警惕风险") |
| | | |
| | | # 信号3:极端波动预警 |
| | | if factors['sentiment']['extreme_ratio'] > 0.1: |
| | | signals.append("极端波动:涨停跌停股超10%") |
| | | |
| | | # 信号4:市场情绪综合 |
| | | if factors['sentiment']['zt_ratio'] > 0.05 and factors['sentiment']['sign'] == 1: |
| | | signals.append("高情绪热度:涨停股多且人气向好") |
| | | |
| | | return signals if signals else ["无显著信号:维持当前策略"] |
| | | |
| | | |
| | | # 实时设置计划持仓数量 函数 |
| | |
| | | # print(f"指数K线{data_cache.all_index_k_line_property_dict}") |
| | | # all_index_k_line_dict_write() |
| | | # ====================== 结果输出 ====================== |
| | | print("========== 因子数值(原生计算) ==========") |
| | | print(f"涨跌比(BDR): {bdr:.2f}") |
| | | print(f"极端波动比例: {extreme_ratio:.2%}") |
| | | print(f"市场宽度因子: {market_breadth:.2f}") |
| | | print(f"分布偏度: {skewness:.2f}, 峰度: {kurtosis:.2f}") |
| | | print(f"data=={data}") |
| | | |
| | | # 因子计算 |
| | | factors = calculate_factors(data) |
| | | |
| | | # 生成信号 |
| | | signals = generate_signals(factors) |
| | | |
| | | # 结果输出 |
| | | print("========== 市场关键指标 ==========") |
| | | print(f"总股票数: {factors['total_stocks']}") |
| | | print(f"涨跌比(BDR): {factors['rise_vs_fall']['rise_vs_fall_ratio']:.2f}") |
| | | print(f"极端波动比例: {factors['sentiment']['extreme_ratio']:.2%}") |
| | | print(f"资金净流入(元): {factors['capital_flow']['net']:,}") |
| | | print(f"涨停股占比: {factors['sentiment']['zt_ratio']:.2%}") |
| | | print(f"市场情绪量化: {'积极' if factors['sentiment']['sign'] else '谨慎'}") |
| | | print(f"上涨聚集区域:{factors['rise_vs_fall']['rise_gather_area']}") |
| | | print(f"上涨零散区域:{factors['rise_vs_fall']['percentages']}") |
| | | |
| | | print("\n========== 策略信号 ==========") |
| | | for i, signal in enumerate(signals, 1): |
| | | print(f"信号{i}: {signal}") |
| | | print(f"信号{i}: {signal}") |