| | |
| | | MODE_NORMAL = 0 |
| | | MODE_FAST = 1 |
| | | MODE_ACTIVE = 2 |
| | | MODE_RADICAL = 3 |
| | | |
| | | # mode: 0-普通交易 1-快速交易 |
| | | def __init__(self, buy_single_index=None, buy_exec_index=-1, buy_compute_index=None, num=0, count=0, |
| | |
| | | from log_module.log import logger_l2_trade_buy, logger_l2_process, logger_l2_error, logger_debug, \ |
| | | logger_l2_not_buy_reasons, logger_real_place_order_position, logger_l2_trade_buy_queue |
| | | |
| | | from trade.trade_data_manager import CodeActualPriceProcessor, PlaceOrderCountManager, AccountMoneyManager |
| | | from trade.trade_data_manager import CodeActualPriceProcessor, PlaceOrderCountManager, AccountMoneyManager, \ |
| | | RadicalBuyDealCodesManager |
| | | |
| | | from trade.trade_manager import TradeTargetCodeModeManager |
| | | |
| | |
| | | # 不处于可下单状态 |
| | | return False |
| | | __start_time = tool.get_now_timestamp() |
| | | order_begin_pos = cls.__get_order_begin_pos( |
| | | code) |
| | | |
| | | can, need_clear_data, reason, is_valid_exec_index = cls.__can_buy_first(code) |
| | | if order_begin_pos.MODE_RADICAL == order_begin_pos.mode: |
| | | # 激进下单不判断条件 |
| | | can, need_clear_data, reason, is_valid_exec_index = True, False, "激进下单", True |
| | | else: |
| | | can, need_clear_data, reason, is_valid_exec_index = cls.__can_buy_first(code) |
| | | |
| | | # __start_time = l2_data_log.l2_time(code, tool.get_now_timestamp() - __start_time, "最后判断是否能下单", force=True) |
| | | # 删除虚拟下单 |
| | | if code in cls.unreal_buy_dict: |
| | | cls.unreal_buy_dict.pop(code) |
| | | |
| | | order_begin_pos = cls.__get_order_begin_pos( |
| | | code) |
| | | if not can: |
| | | if not is_valid_exec_index: |
| | | if cls.__latest_exec_indexes.get(code) and cls.__latest_exec_indexes[code][ |
| | |
| | | return True, "" |
| | | |
| | | @classmethod |
| | | def __is_on_limit_up_buy(cls, code, buy_exec_index): |
| | | total_data = local_today_datas.get(code) |
| | | latest_exec_indexes = cls.__latest_exec_indexes[code] |
| | | if not latest_exec_indexes: |
| | | latest_exec_indexes = [] |
| | | # 判断是否是炸开后买入 |
| | | last_exec_index = 0 |
| | | if len(latest_exec_indexes) > 1: |
| | | last_exec_index = latest_exec_indexes[-2] |
| | | # 获取最近的非涨停价成交时间 |
| | | not_limit_up_trade_time_with_ms = current_price_process_manager.get_trade_not_limit_up_time_with_ms( |
| | | code) |
| | | is_limit_up_buy = True |
| | | if not_limit_up_trade_time_with_ms: |
| | | t1 = int( |
| | | L2DataUtil.get_time_with_ms(total_data[last_exec_index]["val"]).replace(":", "").replace(".", |
| | | "")) |
| | | t2 = int(not_limit_up_trade_time_with_ms.replace(":", "").replace(".", "")) |
| | | t3 = int(L2DataUtil.get_time_with_ms(total_data[buy_exec_index]["val"]).replace(":", "").replace( |
| | | ".", "")) |
| | | if t1 < t2 <= t3: |
| | | # 炸板时间在两次下单时间中间 |
| | | is_limit_up_buy = False |
| | | return is_limit_up_buy |
| | | |
| | | @classmethod |
| | | def __can_buy_first(cls, code): |
| | | """ |
| | | 是否可以下单 |
| | |
| | | # 1.当前成交价为涨停价 |
| | | # 2.距离最近的非板上成交的时间大于一个阈值 |
| | | if abs(limit_up_price - float(trade_price)) < 0.001: |
| | | latest_exec_indexes = cls.__latest_exec_indexes[code] |
| | | if not latest_exec_indexes: |
| | | latest_exec_indexes = [] |
| | | # 判断是否是炸开后买入 |
| | | last_exec_index = 0 |
| | | if len(latest_exec_indexes) > 1: |
| | | last_exec_index = latest_exec_indexes[-2] |
| | | # 获取最近的非涨停价成交时间 |
| | | not_limit_up_trade_time_with_ms = current_price_process_manager.get_trade_not_limit_up_time_with_ms( |
| | | code) |
| | | |
| | | is_limit_up_buy = True |
| | | if not_limit_up_trade_time_with_ms: |
| | | t1 = int( |
| | | L2DataUtil.get_time_with_ms(total_data[last_exec_index]["val"]).replace(":", "").replace(".", |
| | | "")) |
| | | t2 = int(not_limit_up_trade_time_with_ms.replace(":", "").replace(".", "")) |
| | | t3 = int(L2DataUtil.get_time_with_ms(total_data[order_begin_pos.buy_exec_index]["val"]).replace(":", |
| | | "").replace( |
| | | ".", "")) |
| | | if t1 < t2 <= t3: |
| | | # 炸板时间在两次下单时间中间 |
| | | is_limit_up_buy = False |
| | | is_limit_up_buy = cls.__is_on_limit_up_buy(code, order_begin_pos.buy_exec_index) |
| | | if is_limit_up_buy: |
| | | # 板上买且非加绿 |
| | | |
| | | # 获取最近的非涨停价成交时间 |
| | | not_limit_up_trade_time_with_ms = current_price_process_manager.get_trade_not_limit_up_time_with_ms( |
| | | code) |
| | | # 判断成交进度到当前数据的笔数,如果少于10笔且还有未成交的大单(>=299)就可以下单 |
| | | trade_index, is_default = cls.__TradeBuyQueue.get_traded_index(code) |
| | | if trade_index is None: |
| | |
| | | start = None |
| | | return None |
| | | |
| | | # 计算激进买的下单信号 |
| | | # 计算积极买的下单信号 |
| | | @classmethod |
| | | def __compute_active_order_begin_pos(cls, code, continue_count, start_index, end_index): |
| | | """ |
| | |
| | | |
| | | return False, -1, "未获取到激进买的起始信号", '', OrderBeginPosInfo.MODE_NORMAL |
| | | |
| | | # 计算激进买的下单信号 |
| | | @classmethod |
| | | def __compute_radical_order_begin_pos(cls, code, start_index, end_index): |
| | | """ |
| | | 计算激进买入信号: |
| | | 1.非板上放量 |
| | | 2.检测到299万大单买入 |
| | | @param code: |
| | | @param start_index: |
| | | @param end_index: |
| | | @return: (是否获取到信号, 信号位置) |
| | | """ |
| | | # 激进买信号的时间 |
| | | |
| | | |
| | | radical_data = RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict.get(code) |
| | | if not radical_data: |
| | | return False, None, "不满足激进买的条件" |
| | | if t.time() > radical_data[0]: |
| | | return False, None, "超过生效时间" |
| | | |
| | | |
| | | # 判断是否是板上放量 |
| | | if cls.__is_on_limit_up_buy(code, start_index): |
| | | return False, None, "板上放量" |
| | | total_datas = local_today_datas[code] |
| | | min_num = int(29900 / gpcode_manager.get_limit_up_price_as_num(code)) |
| | | single_index = None |
| | | for i in range(start_index, end_index + 1): |
| | | data = total_datas[i] |
| | | val = data["val"] |
| | | if not L2DataUtil.is_limit_up_price_buy(val): |
| | | continue |
| | | if val["num"] < min_num: |
| | | continue |
| | | if int(val["orderNo"]) <= radical_data[1]: |
| | | # 主动买单后的数据不算 |
| | | continue |
| | | single_index = i |
| | | break |
| | | if single_index is not None: |
| | | return True, single_index, "有大单" |
| | | return False, None, "无大单" |
| | | |
| | | @classmethod |
| | | def test__compute_active_order_begin_pos(cls, code, continue_count, start_index, end_index): |
| | | return cls.__compute_active_order_begin_pos(code, continue_count, start_index, end_index) |
| | |
| | | # 是否是涨停 |
| | | if d[1] == limit_up_price: |
| | | # 有涨停主动买 |
| | | L2TradeSingleDataManager.set_limit_up_active_buy(code, datas[-1][3]) |
| | | L2TradeSingleDataManager.set_limit_up_active_buy(code, datas[-1][3], datas[-1][6]) |
| | | break |
| | | except: |
| | | pass |
| | |
| | | @return: |
| | | """ |
| | | |
| | | def OnLimitUpActiveBuy(self, code, huaxin_timestamp): |
| | | def OnLimitUpActiveBuy(self, code, huaxin_timestamp, buy_no): |
| | | """ |
| | | 涨停主动买触发 |
| | | 涨停主动买触发 |
| | | @param code: |
| | | @param huaxin_timestamp: |
| | | @param buy_no: |
| | | @return: |
| | | """ |
| | | |
| | |
| | | # cls.__callback.OnTradeSingle(code, 0, cls.TYPE_ACTIVE, cls.__latest_sell_active_deal_data_dict[code]) |
| | | |
| | | @classmethod |
| | | def set_limit_up_active_buy(cls, code, huaxin_timestamp): |
| | | cls.__callback.OnLimitUpActiveBuy(code, huaxin_timestamp) |
| | | def set_limit_up_active_buy(cls, code, huaxin_timestamp, buy_no): |
| | | cls.__callback.OnLimitUpActiveBuy(code, huaxin_timestamp, buy_no) |
| | | |
| | | @classmethod |
| | | def get_valid_trade_single(cls, code, latest_time_with_ms): |
| | |
| | | from l2.huaxin import huaxin_target_codes_manager, l2_huaxin_util |
| | | from l2.huaxin.huaxin_target_codes_manager import HuaXinL1TargetCodesManager |
| | | from l2.l2_data_manager import TradePointManager, OrderBeginPosInfo |
| | | from l2.l2_data_manager_new import L2TradeDataProcessor |
| | | from l2.l2_data_util import L2DataUtil |
| | | from l2.l2_sell_manager import L2MarketSellManager |
| | | from l2.l2_transaction_data_manager import HuaXinSellOrderStatisticManager, BigOrderDealManager |
| | |
| | | huaxin_trade_record_manager, huaxin_sell_util |
| | | from api.outside_api_command_callback import OutsideApiCommandCallback |
| | | from trade.sell.sell_rule_manager import TradeRuleManager |
| | | from trade.trade_data_manager import RadicalBuyDealCodesManager |
| | | from trade.trade_manager import CodesTradeStateManager |
| | | from utils import socket_util, middle_api_protocol, tool, huaxin_util, global_util |
| | | |
| | |
| | | if huaxin_util.is_deal(order_status): |
| | | if int(str(data["direction"])) == huaxin_util.TORA_TSTP_D_Buy: |
| | | l2_trade_util.forbidden_trade(data["securityID"], msg="已成交", force=True) |
| | | RadicalBuyDealCodesManager().add_deal_code(data["securityID"]) |
| | | # 成交,更新成交列表与资金列表 |
| | | huaxin_trade_data_update.add_deal_list() |
| | | huaxin_trade_data_update.add_money_list() |
| | |
| | | |
| | | |
| | | class MyL2TradeSingleCallback(L2TradeSingleCallback): |
| | | # 积极买板块计算结果缓存:{"code",(有效时间, 结果)} |
| | | __radical_buy_by_blocks_result_cache = {} |
| | | |
| | | def OnTradeSingle(self, code, big_buy_order_count, _type, data): |
| | | # 只处理深证的票 |
| | | try: |
| | |
| | | except Exception as e: |
| | | logger_debug.exception(e) |
| | | |
| | | def OnLimitUpActiveBuy(self, code, huaxin_timestamp): |
| | | def OnLimitUpActiveBuy(self, code, huaxin_timestamp, buy_no): |
| | | try: |
| | | # 判断最近60个交易日有无涨停 |
| | | # 判断昨日是否涨停过 |
| | | async_log_util.info(logger_l2_radical_buy, f"涨停主动买:{code}-{huaxin_timestamp}") |
| | | deal_codes = RadicalBuyDealCodesManager().get_deal_codes() |
| | | if len(deal_codes) >= 2: |
| | | async_log_util.info(logger_l2_radical_buy, f"成交代码个数大于2个:{code}-{deal_codes}") |
| | | return |
| | | if code in deal_codes: |
| | | async_log_util.info(logger_l2_radical_buy, f"该代码已经成交:{code}") |
| | | return |
| | | |
| | | k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code) |
| | | if k_format and k_format[13] and not k_format[14]: |
| | | # 判断是否有大单,判断最近的主动买占了总买额的多少 |
| | | refer_sell_data = L2MarketSellManager().get_refer_sell_data(code, l2_huaxin_util.convert_time( |
| | | huaxin_timestamp)) |
| | | async_log_util.info(logger_l2_radical_buy, f"参考总卖额:{code}-{refer_sell_data}") |
| | | refer_sell_time = refer_sell_data[0] |
| | | # 获取最近的主动买成交量 |
| | | deal_infos = HuaXinSellOrderStatisticManager.get_latest_6s_active_buy_deal_volumes(code) |
| | | async_log_util.info(logger_l2_radical_buy, f"最近主动买成交:{code}-{deal_infos}") |
| | | if refer_sell_data: # and refer_sell_data[1] > 100 * 1e4: |
| | | # 总卖额要大于100w |
| | | deal_volume = 0 |
| | | for i in range(0, len(deal_infos)): |
| | | # >=统计到的总卖 |
| | | if int(refer_sell_time.replace(":", "")) > int(deal_infos[i][0].replace(":", "")): |
| | | break |
| | | deal_volume += deal_infos[i][1] |
| | | async_log_util.info(logger_l2_radical_buy, f"成交量:{deal_volume}/{refer_sell_data[2]}") |
| | | # 判断参考时间之后是否有大单成交 |
| | | big_deal_money_list = BigOrderDealManager().get_total_buy_money_list(code) |
| | | if len(big_deal_money_list) > 0 or True: |
| | | # 有大单成交 |
| | | yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes() |
| | | if yesterday_codes is None: |
| | | yesterday_codes = set() |
| | | result = RadicalBuyBlockManager.is_radical_buy(code, yesterday_codes) |
| | | if result[0]: |
| | | if refer_sell_data[1] < 500 * 1e4: |
| | | async_log_util.info(logger_l2_radical_buy, f"不能扫:{code}-总卖额偏少{refer_sell_data[1]}/500w") |
| | | else: |
| | | async_log_util.info(logger_l2_radical_buy, f"可以扫:{code}-{result}") |
| | | async_log_util.info(logger_l2_radical_buy, f"计算板块结果:{code}-{result}") |
| | | # 获取激进买的板块 |
| | | result = self.__radical_buy_by_blocks_result_cache.get(code) |
| | | if not result or result[0] < time.time(): |
| | | yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes() |
| | | if yesterday_codes is None: |
| | | yesterday_codes = set() |
| | | result = RadicalBuyBlockManager.is_radical_buy(code, yesterday_codes) |
| | | async_log_util.info(logger_l2_radical_buy, f"计算板块结果:{code}-{result}") |
| | | self.__radical_buy_by_blocks_result_cache[code] = (time.time() + 3, result) |
| | | else: |
| | | # 取缓存 |
| | | result = result[1] |
| | | |
| | | if result[0]: |
| | | # 有可以扫的板块 |
| | | # 判断最近的主动买占了总买额的多少 |
| | | refer_sell_data = L2MarketSellManager().get_refer_sell_data(code, l2_huaxin_util.convert_time( |
| | | huaxin_timestamp)) |
| | | async_log_util.info(logger_l2_radical_buy, f"参考总卖额:{code}-{refer_sell_data}") |
| | | if refer_sell_data: |
| | | # 如果总卖额大于500w,成交到一半就直接扫 |
| | | if refer_sell_data[1] >= 500 * 1e4: |
| | | refer_sell_time = refer_sell_data[0] |
| | | # 获取最近的主动买成交量 |
| | | deal_infos = HuaXinSellOrderStatisticManager.get_latest_6s_active_buy_deal_volumes(code) |
| | | async_log_util.info(logger_l2_radical_buy, f"最近主动买成交:{code}-{deal_infos}") |
| | | # 总卖额要大于100w |
| | | deal_volume = 0 |
| | | for i in range(0, len(deal_infos)): |
| | | # >=统计到的总卖 |
| | | if int(refer_sell_time.replace(":", "")) > int(deal_infos[i][0].replace(":", "")): |
| | | break |
| | | deal_volume += deal_infos[i][1] |
| | | async_log_util.info(logger_l2_radical_buy, f"成交量:{deal_volume}/{refer_sell_data[2]}") |
| | | deal_rate = round(deal_volume / refer_sell_data[2], 2) |
| | | if deal_rate > 0.5: |
| | | # 判断参考时间之后是否有大单成交 |
| | | # big_deal_money_list = BigOrderDealManager().get_total_buy_money_list(code) |
| | | # 成交比例大于50% |
| | | total_datas = l2_data_util.local_today_datas.get(code) |
| | | buy_single_index, buy_exec_index = total_datas[-1]["index"], total_datas[-1]["index"] |
| | | buy_volume_rate = L2TradeDataProcessor.volume_rate_info[code][0] |
| | | sell_info = (refer_sell_data[0], refer_sell_data[0]) |
| | | threshold_money = 0 |
| | | order_begin_pos_info = OrderBeginPosInfo(buy_single_index=buy_single_index, |
| | | buy_exec_index=buy_exec_index, |
| | | buy_compute_index=buy_exec_index, |
| | | num=deal_volume // 100, count=1, |
| | | max_num_set=set(), |
| | | buy_volume_rate=buy_volume_rate, |
| | | mode=OrderBeginPosInfo.MODE_RADICAL, |
| | | mode_desc="激进买入", |
| | | sell_info=sell_info, |
| | | threshold_money=threshold_money) |
| | | L2TradeDataProcessor.save_order_begin_data(code, order_begin_pos_info) |
| | | L2TradeDataProcessor.start_buy(code, total_datas[-1], total_datas[-1]["index"], True) |
| | | else: |
| | | # L2委托有大单就扫 |
| | | # 记录买入信号, 3s内有效 |
| | | RadicalBuyDealCodesManager.buy_by_l2_delegate_expire_time_dict[code] = ( |
| | | time.time() + 3, buy_no) |
| | | else: |
| | | volume_rate = code_volumn_manager.get_volume_rate(code) |
| | | async_log_util.info(logger_l2_radical_buy, f"图形不符合要求:{code},量比:{volume_rate}") |
| | |
| | | return self.__mysqldb.select_all(sql) |
| | | |
| | | |
| | | # 激进买成交代码 |
| | | class RadicalBuyDealCodesManager: |
| | | """ |
| | | 激进买成交代码管理 |
| | | """ |
| | | __db = 2 |
| | | __redis_manager = redis_manager.RedisManager(2) |
| | | __deal_codes_cache = set() |
| | | __instance = None |
| | | __mysqldb = Mysqldb() |
| | | # 根据L2数据来激进买入的有效时间:{"code":(有效截至时间, 买单号)} |
| | | buy_by_l2_delegate_expire_time_dict = {} |
| | | |
| | | def __new__(cls, *args, **kwargs): |
| | | if not cls.__instance: |
| | | cls.__instance = super(RadicalBuyDealCodesManager, cls).__new__(cls, *args, **kwargs) |
| | | cls.__instance.__load_data() |
| | | |
| | | return cls.__instance |
| | | |
| | | @classmethod |
| | | def __load_data(cls): |
| | | __redis = cls.__get_redis() |
| | | result = RedisUtils.get(cls.__get_redis(), "radical_buy_deal_codes") |
| | | if result: |
| | | result = json.loads(result) |
| | | cls.__deal_codes_cache = set(result) |
| | | |
| | | @classmethod |
| | | def __get_redis(cls): |
| | | return cls.__redis_manager.getRedis() |
| | | |
| | | def add_deal_code(self, code): |
| | | """ |
| | | 添加已成交的代码 |
| | | @param code: |
| | | @return: |
| | | """ |
| | | self.__deal_codes_cache.add(code) |
| | | RedisUtils.sadd_async(self.__db, "radical_buy_deal_codes", code) |
| | | RedisUtils.expire_async(self.__db, "radical_buy_deal_codes", tool.get_expire()) |
| | | |
| | | def get_deal_codes(self): |
| | | """ |
| | | 获取已经成交的代码 |
| | | @return: |
| | | """ |
| | | if self.__deal_codes_cache: |
| | | return self.__deal_codes_cache |
| | | return set() |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | print(AccountMoneyManager().get_deal_count()) |
| | |
| | | from db import mysql_data_delegate as mysql_data, redis_manager_delegate as redis_manager |
| | | from db.mysql_data_delegate import Mysqldb |
| | | from db.redis_manager_delegate import RedisUtils |
| | | from l2.l2_data_manager import OrderBeginPosInfo |
| | | from log_module import async_log_util |
| | | from output import kp_client_msg_manager |
| | | from trade import trade_data_manager, l2_trade_util, trade_juejin, trade_huaxin, trade_constant |
| | |
| | | |
| | | from log_module.log import * |
| | | from trade.huaxin.huaxin_trade_record_manager import TradeOrderIdManager |
| | | from trade.trade_data_manager import AccountMoneyManager |
| | | from trade.trade_data_manager import AccountMoneyManager, RadicalBuyDealCodesManager |
| | | from utils import import_util, tool, huaxin_util |
| | | |
| | | trade_gui = import_util.import_lib("trade.trade_gui") |
| | |
| | | # 设置交易账户的可用金额 |
| | | |
| | | |
| | | |
| | | # 保存交易成功的数据 |
| | | def save_trade_success_data(datas, day=datetime.datetime.now().strftime("%Y%m%d")): |
| | | time_str = tool.get_now_time_str() |
| | |
| | | try: |
| | | if constant.API_TRADE_ENABLE: |
| | | count = tool.get_buy_volume(price) |
| | | if mode == OrderBeginPosInfo.MODE_RADICAL: |
| | | # 激进买入金额为1手 |
| | | count = 100 |
| | | if constant.TRADE_WAY == constant.TRADE_WAY_JUEJIN: |
| | | trade_juejin.order_volume(code, price, count) |
| | | elif constant.TRADE_WAY == constant.TRADE_WAY_HUAXIN: |
| | |
| | | # 加入黑名单 |
| | | if not l2_trade_util.is_in_forbidden_trade_codes(code): |
| | | l2_trade_util.forbidden_trade(code, "buy success", force=True) |
| | | RadicalBuyDealCodesManager().add_deal_code(code) |
| | | # 取s消所有的挂单 |
| | | if constant.API_TRADE_ENABLE: |
| | | if constant.TRADE_WAY == constant.TRADE_WAY_JUEJIN: |