| | |
| | | """ |
| | | 该模块下进行指数行情策略的编写 |
| | | """ |
| | | import copy |
| | | # import decimal |
| | | import datetime |
| | | import json |
| | | |
| | | import constant |
| | | from log_module.log import logger_common |
| | | # import time |
| | | # 引入掘金API |
| | |
| | | |
| | | # import account_management |
| | | from strategy import order_methods |
| | | from utils import tool |
| | | from strategy.all_K_line import k_line_history |
| | | from utils import tool, juejin_api |
| | | |
| | | # 获取logger实例 |
| | | logger = logger_common |
| | |
| | | return index_trend_expectation_score |
| | | |
| | | |
| | | # 获取指数K线并写入本地的函数 |
| | | def get_index_K_line(): |
| | | all_index_K_line_dict = {} |
| | | for i in data_cache.INDEX_SYMBOL_LIST: |
| | | index_K_line = juejin_api.JueJinApi.history_n(i, "1d", 90, 1, "open,close,high,low,amount,volume,bob") |
| | | # print(f"index_K_line=={index_K_line}") |
| | | all_index_K_line_dict[i] = index_K_line |
| | | # print(f"all_index_K_line=={all_index_K_line_dict}") |
| | | return all_index_K_line_dict |
| | | |
| | | |
| | | # 给指数K线加入属性值 |
| | | def get_property_mark(it_K_line, symbol): |
| | | historical_high_price = 0.01 # 初始化历史最高价 |
| | | historical_low_price = 0.01 # 初始化历史最低价 |
| | | historical_low_price_index = 0 # 初始化历史最高价序号 |
| | | historical_high_price_index = 0 # 初始化历史最低价序号 |
| | | historical_average_price = 0.01 # 初始化历史均价 |
| | | large_amplitude_day = [] # 初始化大幅震荡日期 |
| | | current_count = 0 # 当前连续满足条件的天数 |
| | | start = None |
| | | results = [] |
| | | dates_list = [] |
| | | |
| | | for i in range(0, len(it_K_line) - 1): |
| | | previous_close = it_K_line[i + 1]['close'] # 昨日收盘价 |
| | | previous_high = it_K_line[i + 1]['high'] # 昨日最高价 |
| | | current_open = round(it_K_line[i]['open'], 2) # 当日开盘价 |
| | | current_close = round(it_K_line[i]['close'], 2) # 当日收盘价 |
| | | current_high = round(it_K_line[i]['high'], 2) # 当日最高价 |
| | | current_low = round(it_K_line[i]['low'], 2) # 当日最低价 |
| | | limit_up_price = basic_methods.limit_up_price(previous_close) # 计算出的当天涨停价 |
| | | limit_up_price = float(limit_up_price) # 将涨停价转化为浮点 |
| | | limit_down_price = basic_methods.limit_down_price(previous_close) # 计算出的当天跌停价 |
| | | limit_down_price = float(limit_down_price) # 将跌停价转化为浮点 |
| | | current_today_volume = it_K_line[i]['volume'] # 当日总交易量 |
| | | current_yesterday_volume = it_K_line[i + 1]['volume'] # 昨日总交易量 |
| | | # current_today_amount = it_K_line[i]['amount'] #当日总交易额 |
| | | current_today_growth = basic_methods.intraday_growth(current_close, previous_close) # 计算出当日涨幅 |
| | | it_K_line[i]['today_growth'] = current_today_growth # 将当日涨幅数据添加到字典中对应的日期中 |
| | | current_today_amplitude = round((current_high - current_low) / previous_close, 2) # 计算出当日振幅 |
| | | it_K_line[i]['today_amplitude'] = current_today_amplitude # 将当日振幅数据添加到字典中对应的日期中 |
| | | historical_high_price = round(max(i['high'] for i in it_K_line), 2) # 计算出历史最高价 |
| | | historical_high_price_index = max(range(len(it_K_line)), key=lambda ii: it_K_line[ii]['high']) # 找到最高价的索引 |
| | | historical_low_price = round(min(i['low'] for i in it_K_line), 2) # 计算出历史最低价 |
| | | historical_low_price_index = min(range(len(it_K_line)), key=lambda ii: it_K_line[ii]['low']) # 找到最低价的索引 |
| | | historical_average_price = round((historical_high_price + historical_low_price) / 2, 2) # 计算出历史最均价 |
| | | # 把最高价、最高价序号、最低价、最低价序号,添加到K线的昨日字典中 |
| | | new_properties = { |
| | | 'historical_high_price': historical_high_price, |
| | | 'historical_high_price_index': historical_high_price_index, |
| | | 'historical_low_price': historical_low_price, |
| | | 'historical_low_price_index': historical_low_price_index, |
| | | 'historical_average_price': historical_average_price |
| | | } |
| | | it_K_line[0].update(new_properties) |
| | | |
| | | # 计算大振幅的日期并添加到大振幅日期列表中 |
| | | if not (-4 < it_K_line[i]['today_growth'] < 4): |
| | | large_amplitude_day.append(it_K_line[i]['bob']) |
| | | |
| | | # 判断K线图形风险位置 及 高低时间点 |
| | | if historical_low_price_index > historical_high_price_index: |
| | | # 序列小于1是历史最高价 历史长度90,其实还可以根据更长来判断更显程度,历史长度很短的一般认为具有更高风险,而更长的之前有可能有更高的历史高位还比较远 |
| | | # 最低价在前 |
| | | it_K_line[0]['risk_position'] = 'low_price_ahead' |
| | | ''' |
| | | 以下部分条件分支由于都是对 it_K_line[0]['risk_position'] 数据进行修改, |
| | | 条件判断逻辑有部分重叠,所以应按照逻辑的覆盖面进行先后判断,避免先把大部分过滤掉了。 |
| | | 所以当前条件分支语句的顺序不要轻易更换。 |
| | | # [(historical_high_price / round(it_K_line[0]['close'], 2) < 1.05)的预设值取值范围选择其一: |
| | | # {"均价以上近前高的开盘价":1.05,"接近前高 的跌停价":1.11,"接近前高 的一个炸板加一个跌停的收盘价":1.17,"均价与最高价之间的涨停价":1.21,"均价与最高价之间的价":1.33} |
| | | ''' |
| | | # 最高位据昨日较远 且 昨收价距历史均价差距较小 且 整体涨跌幅度较大 且 最高位 与 最低位为三倍涨幅的妖股【当前二度试探风险】 |
| | | if (2 < historical_high_price_index < 15 and len(it_K_line) >= 90) and ( |
| | | (historical_average_price / round(it_K_line[0]['close'], 2)) < 2) and ( |
| | | historical_high_price > historical_low_price * 3): |
| | | it_K_line[0]['risk_position'] = 'recent_monster_second_break_risk' |
| | | # 最高位据昨日较远 且 昨收价距历史均价差距较小 且 整体涨跌幅度较大 【当前二度突破风险】 |
| | | if (2 < historical_high_price_index < 15 and len(it_K_line) >= 90) and ( |
| | | (historical_average_price / round(it_K_line[0]['close'], 2)) < 1.17) and ( |
| | | historical_high_price > historical_low_price * 1.8): |
| | | it_K_line[0]['risk_position'] = 'recent_second_break_risk' |
| | | # 最高位据昨日较远 且 昨收价距历史最高价差距较小(小于5%,涨幅5%是左右是最容易把低吸骗进去的日内涨幅) 且 整体涨跌幅度较大 【当前二度突破近前高风险】 |
| | | # 【双成药业 2024-11-08 这样的二次近前高,实际数值为1.4646...,为安全起见还是设置为1.5】 |
| | | if (2 < historical_high_price_index < 15 and len(it_K_line) >= 90) and ( |
| | | historical_high_price / round(it_K_line[0]['close'], 2) < 1.5) and ( |
| | | historical_high_price > historical_low_price * 1.8): |
| | | it_K_line[0]['risk_position'] = 'recent_second_break_near_high_position_risk' |
| | | # 昨日就是最高位 且 整体涨跌幅度较大 【当前高位风险】 |
| | | if (historical_high_price_index < 2 and len(it_K_line) >= 90) and ( |
| | | historical_high_price > historical_low_price * 1.8): |
| | | it_K_line[0]['risk_position'] = 'recent_high_position_risk' |
| | | else: |
| | | # 最高价在前 |
| | | it_K_line[0]['risk_position'] = 'high_price_ahead' |
| | | # 最低位据昨日较远 且 昨收价距历史均价差距较小 且 整体涨跌幅度较大 【当前二度崩溃风险】 |
| | | if (2 < historical_low_price_index < 15 and len(it_K_line) >= 90) and ( |
| | | (historical_average_price / round(it_K_line[0]['close'], 2)) > 1.1): |
| | | it_K_line[0]['risk_position'] = 'recent_second_crash_risk' |
| | | # 昨日就是最低位 且 整体涨跌幅度较大 【当前低位风险】 |
| | | if (historical_low_price_index < 2 and len(it_K_line) >= 90) and ( |
| | | historical_high_price > historical_low_price * 1.5): |
| | | it_K_line[0]['risk_position'] = 'recent_low_position_risk' |
| | | |
| | | # 判断K线图形中连续低涨幅天数及具体序列号并把共识价格均价写入文件【阶段性价格共识位置】 |
| | | if 0 < it_K_line[i]['today_amplitude'] < 0.025 and i < 60 and ( |
| | | historical_high_price > historical_low_price * 1.5): |
| | | if current_count == 0: |
| | | start = i |
| | | # 如果当前涨幅小于阈值,增加连续天数计数器 |
| | | current_count += 1 |
| | | # 如果循环复合条件的连续天数达到5天,记录起始索引 |
| | | if current_count > 5: |
| | | # 检查 results 是否为空或当前序列不与最后一个序列重叠 |
| | | if not results or results[-1][1] < start: |
| | | if 0.98 < it_K_line[i]['high'] / it_K_line[start]['low'] < 1.02: |
| | | # 没有重叠,直接添加【其中start为循环到起始序号,i为循环到的结束序号。在实际的日期中要反过来】 |
| | | results.append((start, i)) |
| | | # 算出价格共识区间的均价 |
| | | average_consensus_price = round((it_K_line[i]['high'] + it_K_line[start]['low']) / 2, 2) |
| | | dates_list.append(( |
| | | it_K_line[start]['bob'].strftime('%Y-%m-%d %H:%M:%S'), |
| | | it_K_line[i]['bob'].strftime('%Y-%m-%d %H:%M:%S'), |
| | | average_consensus_price)) |
| | | # if len(dates_list) > 1: # 如果只需要检测包含多段价格共识区 |
| | | it_K_line[0]['rise_and_fall_is_small_start_and_end_date'] = dates_list |
| | | else: |
| | | # 重置计数器 |
| | | current_count = 0 |
| | | start = None |
| | | # 确保不会出现除以零的报错 |
| | | if current_yesterday_volume == 0: |
| | | current_yesterday_volume = 1 |
| | | if round(current_today_volume / current_yesterday_volume, 2) > 1.1: |
| | | # print(f"i=={i} {it_K_line[i]['bob']} {round(current_today_volume/current_yesterday_volume,2)} 【放量】") |
| | | if current_today_growth > 0: |
| | | it_K_line[i]['today_volume_shape'] = 'increases_up' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【放量上涨】") |
| | | elif current_today_growth < 0: |
| | | it_K_line[i]['today_volume_shape'] = 'increases_down' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【放量下跌】") |
| | | else: |
| | | it_K_line[i]['today_volume_shape'] = 'increases_balance' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【放量平收】") |
| | | |
| | | elif round(current_today_volume / current_yesterday_volume, 2) < 0.9: |
| | | # print(f"i=={i} {it_K_line[i]['bob']} {round(current_today_volume/current_yesterday_volume,2)} 【缩量】") |
| | | if current_today_growth > 0: |
| | | it_K_line[i]['today_volume_shape'] = 'decreases_up' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【缩量上涨】") |
| | | elif current_today_growth < 0: |
| | | it_K_line[i]['today_volume_shape'] = 'decreases_down' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【缩量下跌】") |
| | | else: |
| | | it_K_line[i]['today_volume_shape'] = 'decreases_balance' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【缩量平收】") |
| | | else: |
| | | # print(f"i=={i} {it_K_line[i]['bob']} {round(current_today_volume/current_yesterday_volume,2)} 【平量】") |
| | | if current_today_growth > 0: |
| | | it_K_line[i]['today_volume_shape'] = 'remained_up' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【平量上涨】") |
| | | elif current_today_growth < 0: |
| | | it_K_line[i]['today_volume_shape'] = 'remained_down' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【平量下跌】") |
| | | else: |
| | | it_K_line[i]['today_volume_shape'] = 'remained_balance' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 【平量平收】") |
| | | |
| | | if current_open - previous_close > 0: |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 成交总量:{today_volume},,,成交总金额:{today_amount}") |
| | | # difference = current_close - previous_close |
| | | if current_close - current_open > 0: |
| | | it_K_line[i]['attribute'] = 'up_up' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 高开高走 【昨收价:{previous_close} 收盘价:{current_close}】") |
| | | else: |
| | | it_K_line[i]['attribute'] = 'up_down' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 高开低走 【昨收价:{previous_close} 收盘价:{current_close}】") |
| | | else: |
| | | if current_close - current_open > 0: |
| | | it_K_line[i]['attribute'] = 'down_up' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 低开高走 【昨收价:{previous_close} 收盘价:{current_close}】") |
| | | else: |
| | | it_K_line[i]['attribute'] = 'down_down' |
| | | # print(f"i=={i} {it_K_line[i]['bob']} 低开低走 【昨收价:{previous_close} 收盘价:{current_close}】") |
| | | |
| | | # 将高涨跌幅日期打印出来 |
| | | # it_K_line[0]['large_amplitude_day'] = large_amplitude_day |
| | | |
| | | # 判断K线图形长期振幅 及 当前走势 【根据大振幅天数 反推算出 长期低幅度震荡持平、上涨、下跌的个股写入字典】 |
| | | if len(large_amplitude_day) < 1: |
| | | # 长期低幅度震荡 |
| | | it_K_line[0]['long_term_amplitude'] = 'low_amplitude_oscillation' |
| | | # it_K_line[0]['large_amplitude_day_len'] = len(large_amplitude_day) |
| | | if (historical_high_price / historical_low_price) < 1.15: |
| | | if 0.99 < (historical_average_price / round(it_K_line[0]['close'], 2)) < 1.09: |
| | | # 长期低幅度震荡持平 |
| | | it_K_line[0]['long_term_amplitude'] = 'low_amplitude_oscillation_remains_stable' |
| | | else: |
| | | if (historical_low_price_index > historical_high_price_index) and ( |
| | | historical_high_price_index < 2 and len(it_K_line) > 88): |
| | | # 长期低幅度震荡上涨 |
| | | it_K_line[0]['long_term_amplitude'] = 'low_amplitude_oscillation_and_rise' |
| | | elif (historical_low_price_index < historical_high_price_index) and ( |
| | | historical_low_price_index < 2 and len(it_K_line) > 88): |
| | | # 长期低幅度震荡下跌 |
| | | it_K_line[0]['long_term_amplitude'] = 'low_amplitude_oscillation_and_decline' |
| | | |
| | | # 将加入属性值的指数K线下入到本地文件中 |
| | | def all_index_k_line_dict_write(): |
| | | all_index_K_line_dict = get_index_K_line() |
| | | # 初始化所有个股的指标K线列表 |
| | | all_index_k_line_property_dict = {} |
| | | for i in data_cache.INDEX_SYMBOL_LIST: |
| | | # print(f"i==========={i}") |
| | | i_k_line = all_index_K_line_dict[i] # 获取i的K线 |
| | | i_k_line_copy = copy.deepcopy(i_k_line) # 深拷贝i的K线 |
| | | it_K_line_reversed = list(reversed(i_k_line_copy)) # 开盘啦获取的数据需要反转i的K线 |
| | | if not it_K_line_reversed: |
| | | continue |
| | | get_property_mark(it_K_line_reversed, i) # 给标的的K线更新指标属性 把股票代码同时传给要调用的函数 |
| | | symbol_K_line_property_dict = {i: it_K_line_reversed} # 添加 更新极限指标属性的K线 字典 |
| | | # print(f"symbol_K_line_property_dict===={symbol_K_line_property_dict}") |
| | | all_index_k_line_property_dict.update(symbol_K_line_property_dict) |
| | | # print(f"all_index_k_line_property_dict===={all_index_k_line_property_dict}") |
| | | |
| | | # 构造时间格式datetime转化为字符串,以便将K线属性指标转化为json格式写入本地文件 |
| | | def convert_datetime(obj): |
| | | if isinstance(obj, datetime.datetime): |
| | | return obj.strftime('%Y-%m-%d %H:%M:%S') # 转换为字符串 |
| | | elif isinstance(obj, dict): |
| | | return {k: convert_datetime(v) for k, v in obj.items()} # 递归处理字典 |
| | | elif isinstance(obj, list): |
| | | return [convert_datetime(element) for element in obj] # 递归处理列表 |
| | | # 可以添加其他类型的处理逻辑 |
| | | else: |
| | | # 对于未知类型,你可以选择保留原样、跳过或引发异常 |
| | | # 这里我们选择保留原样 |
| | | return obj |
| | | |
| | | try: |
| | | json_data = json.dumps(convert_datetime(all_index_k_line_property_dict), ensure_ascii=False, indent=4) |
| | | # 将转换后的JSON字符串写入文件 |
| | | |
| | | with open(constant.INDEX_K_BARS_PATH, 'w', encoding='utf-8') as f: |
| | | f.write(json_data) |
| | | # print(f"json_data:{json_data}") |
| | | except Exception as error: |
| | | print(f"An error occurred while converting the data to JSON: {error}") |
| | | logger.info(f"加属性的指数k线写完了!{tool.get_now_time_str()}") |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | # all_index_K_line_dict = get_index_K_line() |
| | | |
| | | all_index_k_line_dict_write() |