admin
2025-04-08 70b51a2636858fb8cfbf39d3764d88d07286d8ad
strategy/order_methods.py
@@ -1,36 +1,72 @@
"""
 交易方式模块(总览处理所有渠道的各种交易方法集合)
"""
import logging
import multiprocessing
import threading
# import log
from strategy import data_cache
from strategy import data_cache, account_management
import data_server
from log_module.log import logger_debug
from log_module.log import logger_debug, logger_common
from strategy.trade_setting import TradeSetting
# import account_management
from trade import huaxin_trade_api, huaxin_trade_data_update, middle_api_protocol
from utils import huaxin_util, tool
# 引入日志模块
from strategy.logging_config import get_logger
from trade import huaxin_trade_api
# 获取logger实例
logger = get_logger()
logger = logger_common
# 下单买入函数(按金额,以限价买)【按金额买 基础版】
def buy_order_by_value(symbol, buy_order_value, sec_name, price):
    price = round(float(price), 2)
def buy_order_by_value(symbol, buy_order_value, sec_name, current_price):
    # 自动买 开关监听方法
    if not TradeSetting().get_auto_buy():
        # 暂停自动买
        logger.info(f"在交易方法函数处 关闭了 自动买")
        return
    if current_price < 3 or current_price > 30:
        # 当前单价超出预设限制
        logger.info(f"当前标的个股{sec_name}单价超出预设限制!预设值3 < current_price < 30,当前最新价{current_price}")
        return
    price = round(float(current_price), 2)
    volume = (int(buy_order_value / price) // 100) * 100
    order = huaxin_trade_api.order(1, symbol[-6:], volume, price, blocking=True)
    logger.info(f"order===={order}")
    logger.info(f"买票 执行成功:【{sec_name}】")
    # 买票后添加 持仓代码集合
    data_cache.position_symbols_set.add(symbol)
    # 买票后添加 今日新增持仓代码集合
    data_cache.addition_position_symbols_set.add(symbol)
    logger.info(f"当前持仓数量:::{len(data_cache.position_symbols_set)}")
    logger.info(f"今日新增持仓数量:::{len(data_cache.addition_position_symbols_set)}")
    if volume < 100:
        volume = 100
    # 调用笼子价计算工具计算下单价格
    order_price = round(tool.get_buy_max_price(current_price), 2)
    buy_order = huaxin_trade_api.order(1, symbol[-6:], volume, order_price, blocking=True)
    logger.info(f"current_price===={current_price}    order_price===={order_price}")
    logger.info(f"buy_order===={buy_order}")
    orderStatusMsg = buy_order['data'].get('orderStatusMsg', None)
    statusMsg = buy_order['data'].get('statusMsg', None)
    logger.info(f"orderStatusMsg==={orderStatusMsg}")
    logger.info(f"statusMsg==={statusMsg}")
    # orderStatusMsg 不在buy_order的下单回调中,那么才认为下单成功
    if statusMsg is not None and statusMsg == '':
        logger.info(f"买票 下单成功:【{sec_name}】")
        # 每一次成功下单后要更新一下 缓存 的持仓数据
        account_management.position_management()
        logger.info(f"更新的持仓数据data_cache.account_positions_dict=={data_cache.account_positions_dict}")
        # 调用资金查询函数 查看资金变化
        account_management.finance_management()
        logger.info(f"更新的资金数据data_cache.account_finance_dict=={data_cache.account_finance_dict}")
        if symbol[-6:] in data_cache.account_positions_dict:
            logger.info(f"该股已经持仓==》{sec_name}")
            pass
        # todo 当前为测试阶段的冗余打印
        # 检测持仓信息中有无下单个股且有该个股的当前持仓,只有当前持仓数量不为0时,才认为交易成功
        for i in data_cache.account_positions_dict:
            # print(i)
            if i['securityID'] == symbol[-6:]:
                # print(i['currentPosition'])
                if i['currentPosition'] == 0:
                    logger.info(f"【{i['securityName']}】交易失败~")
                else:
                    # 买票后添加 持仓代码集合
                    data_cache.position_symbols_set.add(symbol)
                    logger.info(f"【{i['securityName']}】交易成功!")
# 下单买入函数(按可用资金的一定比例,在涨停价买)【按金额买 高级版】
@@ -50,161 +86,91 @@
    # 只有持仓数量大于委卖数量才进入买票流程
    if available >= buy_order_value:
        sell_order_by_volume(symbol, buy_order_value, sec_name, today_limit_up_price)
        logger.info(f"【十分之{part_of_value * 10}可用资金】委买完毕,默认成功")
        logger.info(f"【十分之{part_of_value * 10}可用资金】委买完毕")
        data_cache.available = available - buy_order_value
        logger.info(f"买票执行成功:【{sec_name}】")
        logger.info(f"买票后剩余资金:{round(data_cache.available, 2)}")
        logger.info(f"买票后剩余资金:{data_cache.account_finance_dict['usefulMoney']}")
    else:
        logger.info(f"【{sec_name}】,持仓:{available}小于计划委托:{part_of_value},委托失败!")
# 下单卖出函数(按持仓数量,在限价卖)【按量卖 基础版】
def sell_order_by_volume(symbol, volume, sec_name, price):
    price = round(float(price), 2)
    order = huaxin_trade_api.order(2, symbol[-6:], volume, price, blocking=True)
    logger.info(f"order===={order}")
    # order_test = [
    #     {'strategy_id': '507bb60a-a919-11ee-b6ad-0ae0afd621cd',
    #      'account_id': 'aaee2221-839c-11ee-a7cd-00163e022aa6',
    #      'account_name': 'aaee2221-839c-11ee-a7cd-00163e022aa6',
    #      'cl_ord_id': '4a8fff26-7ba6-11ef-8351-00e070c692a6',
    #      'symbol': 'SHSE.600716',
    #      'side': 2,
    #      'position_effect': 2,
    #      'order_type': 1,
    #      'status': 10,
    #      'price': 2.62,
    #      'order_style': 1,
    #      'volume': 3200,
    #      'created_at': datetime.datetime(2024, 9, 26, 9, 26, 1, 751325, tzinfo=datetime.timezone(
    #                                                                            datetime.timedelta(seconds=28800),
    #                                                                            'Asia/Shanghai')),
    #      'order_business': 2,
    #      'properties': {'board': '1', 'origin_product': 'MYQUANT', 'origin_module': 'API', 'sec_type': '1'},
    #      'order_id': '',
    #      'ex_ord_id': '',
    #      'algo_order_id': '',
    #      'position_side': 0,
    #      'order_duration': 0,
    #      'order_qualifier': 0,
    #      'order_src': 0,
    #      'position_src': 0,
    #      'ord_rej_reason': 0,
    #      'ord_rej_reason_detail': '',
    #      'stop_price': 0.0,
    #      'value': 0.0,
    #      'percent': 0.0,
    #      'target_volume': 0,
    #      'target_value': 0.0,
    #      'target_percent': 0.0,
    #      'filled_volume': 0,
    #      'filled_vwap': 0.0,
    #      'filled_amount': 0.0,
    #      'filled_commission': 0.0,
    #      'updated_at': None}]
    logger.info(f"策略ID===={order[0]['strategy_id']}")
    logger.info(f"账号ID===={order[0]['account_id']}")
    logger.info(f"账户登录名===={order[0]['account_name']}")
    logger.info(f"委托客户端ID,下单生成,固定不变(掘金维护,下单唯一标识)===={order[0]['cl_ord_id']}")
    logger.info(f"标的代码===={order[0]['symbol']}")
    logger.info(f"买卖方向===={order[0]['side']}")
    logger.info(f"开平标志===={order[0]['position_effect']}")
    logger.info(f"委托类型===={order[0]['order_type']}")
    logger.info(f"委托状态===={order[0]['status']} ")
    logger.info(f"委托价格===={order[0]['price']}")
    logger.info(f"委托风格===={order[0]['order_style']}")
    logger.info(f"委托量===={order[0]['volume']}")
    logger.info(f"委托业务属性===={order[0]['order_business']}")
    logger.info(f"财产===={order[0]['properties']}")
    # logger.info(f"委托柜台ID(系统字段,下单不会立刻生成,委托报到柜台才会生成)===={order[0]['order_id']}")
    # logger.info(f"委托交易所ID(系统字段,下单不会立刻生成,委托报到柜台才会生成)===={order[0]['ex_ord_id']}")
    # logger.info(f"算法单ID===={order[0]['algo_order_id']}")
    logger.info(f"持仓方向===={order[0]['position_side']}")
    logger.info(f"委托时间属性===={order[0]['order_duration']}")
    logger.info(f"委托成交属性===={order[0]['order_qualifier']}")
    logger.info(f"order_src===={order[0]['order_src']}")
    logger.info(f"头寸来源(系统字段)===={order[0]['position_src']}")
    logger.info(f"委托拒绝原因===={order[0]['ord_rej_reason']}")
    logger.info(f"委托拒绝原因描述===={order[0]['ord_rej_reason_detail']}")
    logger.info(f"stop_price===={order[0]['stop_price']}")
    logger.info(f"委托额===={order[0]['value']}")
    logger.info(f"委托百分比===={order[0]['percent']}")
    logger.info(f"委托目标量===={order[0]['target_volume']}")
    logger.info(f"委托目标额===={order[0]['target_value']}")
    logger.info(f"委托目标百分比===={order[0]['target_percent']}")
    logger.info(f"已成量 (一笔委托对应多笔成交为累计值)===={order[0]['filled_volume']}")
    logger.info(
        f"已成均价,公式为(price*(1+backtest_slippage_ratio)) (仅股票实盘支持,期货实盘不支持)===={order[0]['filled_vwap']}")
    logger.info(
        f"已成金额,公式为(filled_volume*filled_vwap) (仅股票实盘支持,期货实盘不支持)===={order[0]['filled_amount']}")
    logger.info(f"filled_commission===={order[0]['filled_commission']}")
    logger.info(f"委托更新时间===={order[0]['updated_at']}")
    logger.info(f"委托创建时间===={order[0]['created_at']}")
    logger.info(f"卖票 执行成功:【{sec_name}】")
def sell_order_by_volume(symbol, volume, sec_name, current_price):
    # 自动卖开关监听方法
    if not TradeSetting().get_auto_sell():
        # 暂停自动卖
        logger.info(f"在交易方法函数处 关闭了 自动卖")
        return
    # price = round(float(price), 2)
    # 调用笼子价计算工具计算下单价格
    order_price = tool.get_buy_min_price(current_price)
    sell_order = huaxin_trade_api.order(2, symbol[-6:], volume, order_price, blocking=True)
    logger.info(f"current_price===={current_price}    order_price===={order_price}")
    logger.info(f"sell_order===={sell_order}")
    orderStatusMsg = sell_order['data'].get('orderStatusMsg', None)
    statusMsg = sell_order['data'].get('statusMsg', None)
    logger.info(f"orderStatusMsg==={orderStatusMsg}")
    logger.info(f"statusMsg==={statusMsg}")
    # orderStatusMsg 不在buy_order的下单回调中,那么才认为下单成功
    if statusMsg is not None and statusMsg == '':
        logger.info(f"卖票 下单成功:【{sec_name}】")
        # 每一次成功下单后要更新一下 缓存 的持仓数据
        account_management.position_management()
        logger.info(f"更新的持仓数据data_cache.account_positions_dict=={data_cache.account_positions_dict}")
        # 调用资金查询函数 查看资金变化
        account_management.finance_management()
        logger.info(f"更新的资金数据data_cache.account_finance_dict=={data_cache.account_finance_dict}")
# 下单卖出函数(按持仓数量的一定比例,在跌停价卖)【按量卖 高级版】
def sell_order_by_part_volume(part_of_volume, symbol, position_volume_yesterday, today_limit_down_price, sec_name,
def sell_order_by_part_volume(part_of_volume, symbol, position_volume_yesterday, current_price, sec_name,
                              index):
    """
    :param symbol: 代码
    :param position_volume_yesterday: 可用持仓数量
    :param part_of_volume: 计划委卖持仓量的比例
    :param today_limit_down_price: 今日跌停价
    :param current_price: 当前最新价
    :param sec_name: 公司名称
    :param index:  持仓对象列表中的个股对应序列号
    :return:  尝试返回的订单数据
    """
    logger.info(f"当前个股持仓手数==={position_volume_yesterday}")
    logger.info(f"当前个股持仓手数【当前函数被调用时传进来的同步数据data_cache中的持仓数据】==={position_volume_yesterday}")
    # sell_order_volume = int(position_volume_yesterday * part_of_volume)
    sell_order_volume = round(position_volume_yesterday * part_of_volume / 100) * 100
    logger.info(f"当前计划比例==={part_of_volume},当前委托量==={sell_order_volume}")
    # 当委托量大于0
    if sell_order_volume > 0:
        # 只有持仓数量大于委卖数量才进入买票流程
        if position_volume_yesterday >= sell_order_volume:
            sell_order_by_volume(symbol, sell_order_volume, sec_name, today_limit_down_price)
            logger.info(f"【十分之 {round(part_of_volume * 10)} 仓】委卖完毕,默认成功")
            sell_order_by_volume(symbol, sell_order_volume, sec_name, current_price)
            logger.info(f"【十分之 {round(part_of_volume * 10)} 仓】委卖完毕")
            # todo  data_cache.account_positions 数据内容已经变化需重新写,似乎不用计算剩余持仓量,直接请求就行了
            # 计算并更新剩余可用持仓数量
            data_cache.account_positions[index]['volume'] = position_volume_yesterday - sell_order_volume
            if data_cache.account_positions[index]['volume'] <= 0:
                logger.info(f"data_cache.account_positions == {data_cache.account_positions}")
                logger.info(f"下单后,【{sec_name}】的剩余可用持仓数量==={data_cache.account_positions[index]['volume']}")
            # data_cache.account_positions[index]['volume'] = position_volume_yesterday - sell_order_volume
            if data_cache.account_positions_dict[index]['currentPosition'] <= 0:
                logger.info(f"data_cache.account_positions == {data_cache.account_positions_dict}")
                logger.info(f"下单后,【{sec_name}】的剩余可用持仓数量==={data_cache.account_positions_dict[index]['currentPosition']}")
                # 本票本次卖票,可用仓位为0或小于0,,移除【可用持仓代码】集合
                '''
                全局变量中的可用个股数量,由于只在【集合竞价】阶段用,如果移除会影响进入次数,暂不考虑使用
                '''
                # data_cache.available_symbols_set.remove(symbol)
                # logger.info(f"【{sec_name}】当日可用仓位数卖完了")
                # logger.info(f"卖后可用持仓票数:::{len(data_cache.available_symbols_set)}")
            if symbol in data_cache.account_positions:
                for i in data_cache.account_positions:
                    if i['symbol'] == symbol:
                        logger.info(f"下单后【{sec_name}】持仓手数volume==={i['volume']}")
                        if i['volume'] == 0:
                            # 本票本次卖票,全部持仓仓位为0,,移除【持仓代码】集合
                            data_cache.position_symbols_set.remove(symbol)
                            logger.info(f"【{sec_name}】的持仓已经卖完了,或代码已经不在持仓中")
                            logger.info(f"卖后持仓票数:::{len(data_cache.position_symbols_set)}")
                logger.info(f"【{sec_name}】当日可用仓位数卖完了")
                logger.info(f"卖后可用持仓票数:::{len(data_cache.available_symbols_set)}")
        else:
            logger.info(
                f"【{sec_name}】,可用持仓:{position_volume_yesterday}小于计划委托:{sell_order_volume},无法委托,直接平仓!")
            sell_order_by_volume(symbol, position_volume_yesterday, sec_name, today_limit_down_price)
            sell_order_by_volume(symbol, position_volume_yesterday, sec_name, current_price)
            # 计算并更新剩余可用持仓数量
            data_cache.account_positions[index]['volume'] = position_volume_yesterday - position_volume_yesterday
            # data_cache.account_positions_dict[index]['currentPosition'] = position_volume_yesterday - position_volume_yesterday
    else:
        logger.info(f"委托量小于等于零,委托失败!")
        logger.info(
            f"【{sec_name}】,可用持仓:{position_volume_yesterday},计划委托:{sell_order_volume}<=0 ?,无法委托,直接委卖100!")
        sell_order_by_volume(symbol, 100, sec_name, today_limit_down_price)
        # 计算并更新剩余可用持仓数量
        data_cache.account_positions[index]['volume'] = position_volume_yesterday - 100
        sell_order_by_volume(symbol, 100, sec_name, current_price)
def run():
@@ -215,7 +181,19 @@
            :param order_info: {'sinfo': 'b_603682_1736312765623', 'securityID': '603682', 'orderLocalID': '8100043081', 'direction': '0', 'orderSysID': '110018100043081', 'insertTime': '13:06:04', 'insertDate': '20250108', 'acceptTime': '13:05:46', 'cancelTime': '', 'limitPrice': 6.45, 'accountID': '00032047', 'orderRef': 130608, 'turnover': 6410.0, 'volume': 1000, 'volumeTraded': 1000, 'orderStatus': '4', 'orderSubmitStatus': '1', 'statusMsg': ''}
            :return:
            """
            print(f"收到订单回调:{order_info}")
            logger_debug.info(f"收到订单回调:{order_info}")
            if huaxin_util.is_deal(order_info['orderStatus']):
                # 成交,需要更新持仓/委托/成交
                huaxin_trade_data_update.add_position_list()
                huaxin_trade_data_update.add_delegate_list("成交")
                huaxin_trade_data_update.add_deal_list()
            else:
                huaxin_trade_data_update.add_money_list()
                huaxin_trade_data_update.add_delegate_list("订单状态变化")
            # 推送订单数据
            threading.Thread(target=lambda: middle_api_protocol.push(
                middle_api_protocol.load_push_msg({"type": "order", "data": order_info})), daemon=True).start()
    queue = multiprocessing.Queue()
    huaxin_trade_api.run_trade(queue, MyTradeCallback())