admin
2025-02-20 36731498e1b7c65a69cd15d626fedca4c92c1042
增加撤单
2个文件已删除
19个文件已修改
1135 ■■■■■ 已修改文件
constant.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
data_server.py 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
huaxin_client/command_manager.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
huaxin_client/l1_api_client.py 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.py 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/account_management.py 174 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/all_K_line.py 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/all_fundamentals.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/buying_strategy.py 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/check_timer.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/data_cache.py 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/instant_time_market.py 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/kpl_api.py 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/message_analysis.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/order_methods.py 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/selling_strategy.py 129 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/shared_memory_util.py 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
strategy/subscribe_market.py 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/huaxin_trade_api.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/juejin_api.py 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/tool.py 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
constant.py
@@ -67,8 +67,10 @@
# K线路径
K_BARS_PATH = f"{DATA_DIR_PATH}/all_stocks_all_K_line_property_dict.json"
KPL_LIMIT_UP_DATA_PATH = f"{DATA_DIR_PATH}/limit_up_block_date_data.json"
# 每日涨停概念记录数据
KPL_LIMIT_UP_DATA_PATH = f"{DATA_DIR_PATH}/limit_up_block_date_data.jsonl"
# 日内所有股票开盘数据存储
KPL_LIMIT_UP_BLOCK_NAMES_PATH = f"{DATA_DIR_PATH}/limit_up_block_names.json"
data_server.py
@@ -133,6 +133,17 @@
                # 买入
                code = params.get("code")  # 代码
                volume = params.get("volume")  # 量
                price = params.get("price")
                if not price:
                    # 没有上传价格,就需要获取最近的价格进行买入
                    data = data_cache.latest_code_market_info_dict.get(code)
                    if not data:
                        raise Exception("没有获取到L1数据")
                    pre_price = data[1]
                    current_price = data[2] if data[2] else data[5][0][0]
                    price = tool.get_buy_max_price(current_price)
                    price = min(price, tool.get_limit_up_price(code,pre_price))
                else:
                price = round(params.get("price"), 2)  # 价格
                result = huaxin_trade_api.order(1, code, volume, price, blocking=True)
                result_str = json.dumps(result)
@@ -146,6 +157,17 @@
                print("卖出", params)
                code = params.get("code")  # 代码
                volume = params.get("volume")  # 量
                price = params.get("price")
                if not price:
                    # 没有上传价格,就需要获取最近的价格进行买入
                    data = data_cache.latest_code_market_info_dict.get(code)
                    if not data:
                        raise Exception("没有获取到L1数据")
                    pre_price = data[1]
                    current_price = data[2] if data[2] else data[5][0][0]
                    price = tool.get_buy_min_price(current_price)
                    price = max(price, tool.get_limit_down_price(code, pre_price))
                else:
                price = round(params.get("price"), 2)  # 价格
                result = huaxin_trade_api.order(2, code, volume, price, blocking=True)
                result_str = json.dumps(result)
huaxin_client/command_manager.py
@@ -119,7 +119,6 @@
                        _type = val["type"]
                        if _type != "test":
                            async_log_util.info(logger_local_huaxin_contact_debug, f"接受到信息: {val}")
                            # TODO 测试
                            logger_info.info(f"接受到信息: {val}")
                        cls.process_command(_type, None, val)
                except Exception as e:
huaxin_client/l1_api_client.py
@@ -151,7 +151,7 @@
                                 "bob": datetime.strptime(r['TradingDay'], '%Y%m%d'),
                                 "amount": r["Turnover"]
                                 })
            print("ReqReqQryStockDayQuotation:", len(fresults))
            # print("ReqReqQryStockDayQuotation 90天K线:", len(fresults))
            return fresults
        except Exception as e:
@@ -211,7 +211,7 @@
        else:
            self.__result_cache[nRequestID] = self.__temp_cache[nRequestID]
            self.__temp_cache.pop(nRequestID)
            print("OnRspInquiryShareCalendar:", self.__result_cache[nRequestID])
            # print("OnRspInquiryShareCalendar:", self.__result_cache[nRequestID])
    def OnRspInquiryStockDayQuotation(self, pStockDayQuotation, pRspInfo, nRequestID, bIsPageLast, bIsTotalLast):
        """
@@ -240,7 +240,7 @@
        else:
            self.__result_cache[nRequestID] = self.__temp_cache[nRequestID]
            self.__temp_cache.pop(nRequestID)
            print("OnRspInquiryStockDayQuotation:", len(self.__result_cache[nRequestID]))
            # print("OnRspInquiryStockDayQuotation 90天K线:", len(self.__result_cache[nRequestID]))
def __read_request(request_queue: multiprocessing.Queue, response_queue: multiprocessing.Queue):
main.py
@@ -2,9 +2,7 @@
from __future__ import print_function, absolute_import, unicode_literals
import logging
import json
import multiprocessing
import os.path
# import multiprocessing
# from log import logger
import threading
import time
@@ -18,15 +16,14 @@
# 引入历史K线方法模块
# 引入瞬时分时行情模块
# 引入账户管理模块【进行资金和仓位管理】
from strategy import kpl_api, data_cache, check_timer, all_K_line, instant_time_market, account_management
from strategy import kpl_api, data_cache, check_timer, all_K_line, instant_time_market, account_management, order_methods
from huaxin_client import l2_market_client
from log_module import async_log_util
# 引入日志模块
from strategy.logging_config import get_logger
from strategy import order_methods
from trade import huaxin_trade_data_update
from utils import hx_qc_value_util
# 引入日志模块
from strategy.logging_config import get_logger
# 获取logger实例
logger = get_logger()
# 引入行情订阅模块
@@ -46,16 +43,26 @@
def init_data():
    # logging.info("main初始化数据开始")
    logger.info(f"main初始化数据开始")
    # 初始化所有目标票标的信息
    data_cache.all_stocks = utils.juejin_api.JueJinApi.get_target_codes()
    # 获取K线
    '''
    资金管理初始化
    仓位管理初始化
    都在main的初始化数据函数里面完成
    无需掘金考虑的线程或进程方式实现
    '''
    # 初始化账户仓位管理数据
    account_management.finance_management()
    # 初始化账户仓位管理数据
    account_management.position_management()
    # 初始化.实例化缓存中的全局数据
    data_cache.DataCache()
    # 初始化A股所有目标票标的信息
    data_cache.all_stocks = utils.juejin_api.JueJinApi.get_target_codes()
    # 获取目标票标的K线
    all_K_line.k_line_history.init(data_cache.DataCache().today_date, data_cache.DataCache().next_trading_day,
                                   data_cache.DataCache().filtered_stocks)
    # 调用指标K线写入本地文件
    all_K_line.all_stocks_all_k_line_dict_write()
    # 直接调用指标K线写入本地文件
    # all_K_line.all_stocks_all_k_line_dict_write()
    # 先使用json.load()直接从文件中读取【已经存储在本地的K线指标属性字典】并解析JSON数据
    if os.path.exists(constant.K_BARS_PATH):
@@ -63,9 +70,6 @@
            data_cache.all_stocks_all_K_line_property_dict = json.load(f)
            print(
                f"data_cache.all_stocks_all_K_line_property_dict的个数==={len(data_cache.all_stocks_all_K_line_property_dict)}")
    # current_data_info = current(symbols='SHSE.603839', fields='open')
    # print(f"current_data_info==={current_data_info}")
# 第一步:初始化context函数,并开启获取实时数据的线程
@@ -79,19 +83,6 @@
    # 实时检测是否拉取K线线程
    threading.Thread(target=lambda: all_K_line.check_time_and_data_date(), daemon=True).start()
    # print(f"all_stocks_all_K_line_property_dict== {type(data_cache.all_stocks_all_K_line_property_dict)}")
    '''
    目前设想,买只需要进行账户管理,卖才需要仓位管理,而卖在通过行情订阅实现
    并且行情订阅在另一个进程里面,所以目前不需要同时调用
    # 初始化资金管理,下单买逻辑才会有数据
    account_management.position_management(context)
    # 初始化仓位管理,下单卖逻辑才会有数据
    account_management.position_management(context)
    '''
    # TODO 此处注释,要替换context
    # threading.Thread(target=account_management.finance_management_process, args=(context,), daemon=True).start()
    # threading.Thread(target=account_management.position_management_process, args=(context,), daemon=True).start()
    #  开盘啦的涨停概念的回调函数
    def kpl_limit_up_process(datas):
@@ -115,9 +106,6 @@
    threading.Thread(target=kpl_api.get_market_sift_plate_its_stock_power_process,
                     args=(get_market_sift_plate_its_stock_power_process,), daemon=True).start()
    # 行情订阅,沪深300指数【在on_tick函数中去打印tick 数据】
    # subscribe('SHSE.000300', frequency='tick', count=1, unsubscribe_previous=False)
    # 初始化get_current_data方法函数,下单买逻辑才会运行中。。。【核心主线程,随时考虑其启动顺序】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    # threading.Thread(target=lambda: instant_time_market.get_current_data(), daemon=True).start()
@@ -134,26 +122,6 @@
    # kpl_api.get_all_stocks_plate_dict(data_cache.min_stocks)
# 委托状态更新事件
def on_order_status(context, order):
    # 可在后面执行其他处理逻辑
    logger.info(f"context====main————{context}")
    logger.info(f"order====main————{order}")
# 委托执行回报事件
def on_execution_report(context, execrpt):
    logger.info(f"execrpt>context===={context}")
    logger.info(f"execrpt===={execrpt}")
# 交易账户状态更新事件 (交易账户状态对象,仅响应 已连接,已登录,已断开 和 错误 事件。)
def on_account_status(context, account):
    logger.info(f"account>context===={context}")
    logger.info(f"account===={account}")
    logger.info(account)
# 第三步:执行策略的初始设置
if __name__ == '__main__':
    class MyMarketDataCallback(l2_market_client.L2MarketDataCallback):
@@ -164,7 +132,7 @@
            :return:
            """
            data_cache.latest_code_market_info_dict = {x[0]: x for x in datas}
            instant_time_market.process_current_infos(datas)
            instant_time_market.get_current_info()
    # 启动异步日志
strategy/account_management.py
@@ -1,104 +1,114 @@
"""
账户管理模块【管理账户下面的资金管理方法及仓位管理方法等】
"""
import time
import datetime
import decimal
# import time
# import datetime
# import decimal
from trade import huaxin_trade_api
# import logging
# import threading
# 引入全局变量模块
from strategy import data_cache
# 引入日志模块
from strategy.logging_config import get_logger
# 获取logger实例
logger = get_logger()
# 资金管理函数
def finance_management(context):
    account_finance = context.account(account_id=data_cache.account_id).cash
    data_cache.account_finance = account_finance
    data_cache.available = context.account(account_id=data_cache.account_id).cash.available
    # print(f"账户对象列表==={data_cache.account_finance}")
    # print(f"资金初始时间==={data_cache.account_finance.created_at}")
    # print(f"资金变更时间==={data_cache.account_finance.updated_at}")
def finance_management():
    account_finance = huaxin_trade_api.get_money()
    # logger.info(f"account_finance==={account_finance}")
    # print(f"总资金==={round(account_finance.nav, 2)}")
    # print(f"可用资金==={round(account_finance.available, 2)}")
    # print(f"持仓占用资金==={account_finance.frozen}")
    # print(f"冻结资金==={account_finance.order_frozen}")
    # print(f"盈亏===={account_finance.pnl}")
    # print(f"持仓浮动盈亏==={round(data_cache.account_finance.fpnl, 2)}")
    # print(f"持仓市值==={round(data_cache.account_finance.market_value, 2)}")
    # print(f"资金余额==={account_finance.balance}")
    # print(f"累计出入金额==={account_finance.cum_inout}")
    # print(f"累计交易金额==={account_finance.cum_trade}")
    # print(f"累计盈亏==={account_finance.cum_pnl}")
    # print(f"累计委托==={account_finance.cum_commission}")
    # print(f"最后一笔交易==={account_finance.last_trade}")
    # print(f"最后一笔委托==={account_finance.last_commission}")
    # print(f"最后一笔出入金额==={account_finance.last_inout}")
    # print(f"允许保释??==={account_finance.enable_bail}")
    # print(f"纯浮动盈亏??==={account_finance.fpnl_diluted}")
    # 保持开启 , 为了实现永不完成这堆初始化线程 ,因为一旦完成,整体获取current数据变慢为15S+
    # while True:  # 不得擅动!!!
    #     time.sleep(10)
    if account_finance is not None and account_finance['code'] == 0:
        data_cache.account_finance_dict = account_finance['data']
        logger.info(f"data_cache.account_finance_dict==={data_cache.account_finance_dict}")
        usefulMoney = data_cache.account_finance_dict[0]['usefulMoney']  # 可用资金
        frozenCash = data_cache.account_finance_dict[0]['frozenCash']  # 冻结的资金
        fetchLimit = data_cache.account_finance_dict[0]['fetchLimit']  # 可取资金
        preDeposit = data_cache.account_finance_dict[0]['preDeposit']  # 上日结存
        print(f"可用资金==={usefulMoney}")
        print(f"冻结的资金==={frozenCash}")
        print(f"可取资金==={fetchLimit}")
        print(f"上日结存==={preDeposit}")
# finance_management()
# 构造循环请求资金管理线程
def finance_management_process(context):
    while True:
        try:
            # now_start = time.time()
            # print(f"finance_management开始{now_start}")
            finance_management(context)
            # now_end = time.time()
            # print(f"finance_management完成一下{now_end}")
        except Exception as error:
            print(f"获取资金管理线程报错An error occurred: {error}")
        finally:
            time.sleep(60)
# def finance_management_process():
#     while True:
#         try:
#             # now_start = time.time()
#             # print(f"finance_management开始{now_start}")
#             finance_management()
#             # now_end = time.time()
#             # print(f"finance_management完成一下{now_end}")
#         except Exception as error:
#             print(f"获取资金管理线程报错An error occurred: {error}")
#         finally:
#             time.sleep(1)
# 仓位管理函数
def position_management(context):
    # 仓位管理及查询函数
    data_cache.account_positions = context.account(account_id=data_cache.account_id).positions()  # 查询当前账户全部持仓
    # print(f"持仓数量的变化?==={len(data_cache.account_positions)}")
    for i in data_cache.account_positions:
        symbol = i['symbol']  # 当前个股代码
        symbol_code = symbol.split('.')[1]  # 将symbol转为纯数字编号
        available_now = i['available_now']  # 当前个股可用金额
        # # price = d['price']   #当前行情价,,,非最新价,没有实际意义不要用!!!
        # vwap = i['vwap']       #当前个股持仓均价/成本价
        # volume = i['volume']   #当前个股持仓量?
        # volume_today = i['volume_today']  # 今日持仓量
        # volume_yesterday = volume - volume_today  # 昨日持仓量
        # price = current(symbol, fields='price')[0]['price']  # 获取当前个股最新价
        # # print(symbol,available_now, price, vwap)
        # instruments = get_instruments(symbols=symbol, exchanges=None, sec_types=None, names=None,  # 获取当前个股基本信息
        #                               fields="symbol,sec_name,pre_close,upper_limit",
        #                               df=False)
        data_cache.position_symbols_set.add(i['symbol'])
def position_management():
    # 仓位查询函数
    account_positions = huaxin_trade_api.get_position_list()
    if account_positions is not None and account_positions['code'] == 0:
        logger.info(f"持仓数据的长度==={len(account_positions['data'])}")
        logger.info(f"持仓data==={account_positions['data']}")
        data_cache.account_positions_dict = account_positions['data']
        for i in data_cache.account_positions_dict:
            # logger.info(f"i={i}")
            # i={'investorID': '00044396', 'tradingDay': '20250214', 'securityName': '海南华铁', 'securityID': '603300', 'historyPos': 0, 'historyPosFrozen': 0, 'todayBSPos': 500, 'todayBSPosFrozen': 0, 'historyPosPrice': 7.945, 'totalPosCost': -80.25846370000727, 'prePosition': 11000, 'availablePosition': 0, 'currentPosition': 500, 'openPosCost': 4250.0, 'todayCommission': 79.6604637, 'todayTotalBuyAmount': 4250.0, 'todayTotalSellAmount': 91657.0}
            # symbol = i['symbol']  # 当前个股代码
            securityName = i['securityName']  # 当前个股名称
            securityID = i['securityID']  # 当前个股代码
            # symbol_code = symbol.split('.')[1]  # 将symbol转为纯数字编号
            historyPos = i['historyPos']  # 昨日仓位转入数量(昨仓)
            historyPosFrozen = i['historyPosFrozen']       # 昨仓冻结
            todayBSPos = i['todayBSPos']   # 今日买卖仓位转入转出数量
            todayBSPosFrozen = i['todayBSPosFrozen']  # 今买卖仓冻结
            historyPosPrice = i['historyPosPrice']  # 昨仓成本价
            totalPosCost = i['totalPosCost']  # 持仓成本
            prePosition = i['prePosition']  # 上次余额(盘中不变)
            currentPosition = i['currentPosition']  # 股份余额  (总持仓股份数量)
            availablePosition = i['availablePosition']  # 股份可用 (可用股份数量)
            openPosCost = i['openPosCost']  # 开仓成本(开仓资金)
            todayCommission = i['todayCommission']  # 今手续费
            todayTotalBuyAmount = i['todayTotalBuyAmount']  # 当日累计买入金额
            todayTotalSellAmount = i['todayTotalSellAmount']  # 当日累计卖出金额
        # print(f" 当前代码 = {i['symbol']}  持仓均价 = {i['vwap']}    持仓手数=={i['volume']}   可用金额=={i['available_now']} ")
        if available_now != 0:  # 如果可用资金不等于0  昨日收盘价获取到非0值时(不知名原因导致有些票会获取到0值导致后续公式报错,阻止intraday_growth函数正常运行)
            if currentPosition != 0:
                # 当前持仓
                # print(f"当前持仓=={securityName}")
                if availablePosition != 0:  # 如果可用资金不等于0  昨日收盘价获取到非0值时(不知名原因导致有些票会获取到0值导致后续公式报错,阻止intraday_growth函数正常运行)
            # print(f"持仓可用股{symbol}")
            data_cache.available_symbols_set.add(symbol)
                    logger.info(f"今日持仓可用==={securityName}")
                    data_cache.available_symbols_set.add(securityID)
        else:
            data_cache.addition_position_symbols_set.add(symbol)
    # print(f"仓位管理启动时持仓===================================【{data_cache.position_symbols_set}】")
    # print(f"仓位管理前持仓数量===================================【{len(data_cache.position_symbols_set)}】")
    # print(f"今日可用持仓数量====================================【{len(data_cache.available_symbols_set)}】")
    # print(f"今日新增持仓数量====================================【{len(data_cache.addition_position_symbols_set)}】")
                    # 新增持仓
                    logger.info(f"今日新增持仓==={securityName}")
                    data_cache.addition_position_symbols_set.add(securityID)
        # todo 自主的计算持仓数量 管用 还是 服务端即时查询同步有用 有待验证
        logger.info(f"今日可用持仓数量====================================【{len(data_cache.available_symbols_set)}】")
        logger.info(f"今日新增持仓数量====================================【{len(data_cache.addition_position_symbols_set)}】")
# 构造循环请求仓位管理线程
def position_management_process(context):
    while True:
        try:
            # now_start = time.time()
            # print(f"position_management开始{now_start}")
            position_management(context)
            # now_end = time.time()
            # print(f"position_management完成一下{now_end}")
        except Exception as error:
            print(f"获取仓位管理线程报错An error occurred: {error}")
        finally:
            time.sleep(1)
# position_management()
# # 构造循环请求仓位管理线程
# def position_management_process():
#     while True:
#         try:
#             # now_start = time.time()
#             # print(f"position_management开始{now_start}")
#             position_management()
#             # now_end = time.time()
#             # print(f"position_management完成一下{now_end}")
#         except Exception as error:
#             print(f"获取仓位管理线程报错An error occurred: {error}")
#         finally:
#             time.sleep(1)
strategy/all_K_line.py
@@ -3,7 +3,7 @@
from __future__ import print_function, absolute_import, unicode_literals
import copy
import logging
# import logging
import os
import time
import datetime
@@ -12,7 +12,7 @@
import constant
# 引入掘金API
import utils.juejin_api
# import utils.juejin_api
# import kpl_api
from strategy import data_cache
@@ -99,8 +99,6 @@
        # 查询交易标的基本信息并赋值
        sec_name = data_cache.DataCache().code_name_dict.get(symbol)
        # print(f"K_line_sec_name=={sec_name}")
        # TODO 查询代码名称
        # instruments = get_instruments(symbols=symbol, exchanges=None, sec_types=None, names=None, fields="sec_name", df=False)[0]
        # 将获取到的公司名称直接 生成字典放到 K线的第一个序列中
        it_K_line[0]['sec_name'] = sec_name
        for i in range(0, len(it_K_line) - 1):
@@ -382,7 +380,7 @@
            f.write(json_data)
    except Exception as error:
        print(f"An error occurred while converting the data to JSON: {error}")
    print(f"历史k线写完了!{tool.get_now_time_str()}")
    logger.info(f"历史k线写完了!{tool.get_now_time_str()}")
# 用开盘啦数据检测昨日的K线中涨停属性是否有误(盘尾 集合竞价 炸开一个卖一档,但涨幅未变的)
@@ -390,8 +388,7 @@
    for key, values in data_cache.all_stocks_all_K_line_property_dict.items():
        # print(f"data_cache.limit_up_code_list==={data_cache.limit_up_code_list}")
        if 'attribute' in values[0]:
            if key not in data_cache.yesterday_limit_up_code_list and values[0][
                'attribute'] in data_cache.limit_up_type:
            if key not in data_cache.yesterday_limit_up_code_list and values[0]['attribute'] in data_cache.limit_up_type:
                logger.info(f"在K线中昨日涨停,但是在开盘啦中没有,key==={key}       公司名称==={values[0]['sec_name']} ")
                data_cache.yesterday_frying_plate_last_minute_list.append(key)
        else:
@@ -439,6 +436,7 @@
                # 否者还是得调用K线对象方法拉取,并重新读取赋值全局化
                # if hour < 18 or (hour == 18 and minute < 31):
                if now_time < data_cache.update_data_time:
                # if now_time < data_cache.closing_time:
                    check_pre_trading_day = check_data_date(data_cache.DataCache().pre_trading_day)
                    if check_pre_trading_day is True:
                        # if hour >= 17:
@@ -459,14 +457,12 @@
                                    f"data_cache.all_stocks_all_K_line_property_dict的个数{len(data_cache.all_stocks_all_K_line_property_dict)}")
                else:
                    check_today_date = check_data_date(data_cache.DataCache.today_date)
                    check_today_date = check_data_date(data_cache.DataCache().today_date)
                    if check_today_date is True:
                        pass
                        print(
                            f"到了【18:31】 但 既有数据 【是】 本交易日数据 【不执行拉取K线】  ε=ε=ε=ε=ε=ε=ε=ε=ε=ε=ε=ε=ε(/’-‘)/")
                        print(f"到了【18:31】 但 既有数据 【是】 本交易日数据 【不执行拉取K线】  ε=ε=ε=ε=ε=ε=ε=ε=ε=ε=ε=ε=ε(/’-‘)/")
                    else:
                        print(
                            f"到了【18:31】 且 既有数据 【不是】 本交易日数据 执行拉取K线  【既有数据日期:{data_cache.all_stocks_all_K_line_property_dict['SZSE.000034'][0]['bob'][:10]} 本交易日:{data_cache.DataCache.today_date}】")
                            f"到了【18:31】 且 既有数据 【不是】 本交易日数据 执行拉取K线  【既有数据日期:{data_cache.all_stocks_all_K_line_property_dict['SZSE.000034'][0]['bob'][:10]} 本交易日:{data_cache.DataCache().today_date}】")
                        # 调用指标K线写入本地文件
                        all_stocks_all_k_line_dict_write()
                        # 读取已经获取到并存储在本地的所有票的指标K线字典,并赋值给data_cache全局缓存
@@ -477,7 +473,7 @@
                                print(
                                    f"data_cache.all_stocks_all_K_line_property_dict的个数{len(data_cache.all_stocks_all_K_line_property_dict)}")
        except Exception as error:
            logging.exception(error)
            logger.exception(error)
            print(f"实时检测是否拉取K线线程报错An error occurred: {error}")
        finally:
            current_time = datetime.datetime.now()
strategy/all_fundamentals.py
@@ -1,8 +1,8 @@
'''
获取所有股票基本面数据
'''
# 引入掘金API
# todo  解决掘金api 数据 的引入问题
from gm.api import *
# 引入基础方法
import basic_methods
@@ -10,13 +10,13 @@
import data_cache
# 调用推算前N日交易日期的函数
start_time_data = basic_methods.pre_num_trading_day(data_cache.DataCache.today_date, 90)
start_time_data = basic_methods.pre_num_trading_day(data_cache.DataCache().today_date, 90)
'''
股票交易衍生表
'''
# trading_derivative_indicator = get_fundamentals(table='trading_derivative_indicator', symbols='SHSE.601777', start_date=start_time_data, end_date=data_cache.today_date, fields='DY,EV,EVEBITDA,EVPS,LYDY,NEGOTIABLEMV,PB,PELFYNPAAEI,PETTMNPAAEI,TURNRATE', df=True)
# print(f"trading_derivative_indicator===\n{trading_derivative_indicator}")
trading_derivative_indicator_1 = get_fundamentals(table='trading_derivative_indicator', symbols='SZSE.000890', start_date=start_time_data, end_date=data_cache.DataCache.today_date, fields='NEGOTIABLEMV', df=False)
trading_derivative_indicator_1 = get_fundamentals(table='trading_derivative_indicator', symbols='SZSE.000890', start_date=start_time_data, end_date=data_cache.DataCache().today_date, fields='NEGOTIABLEMV', df=False)
# print(f"trading_derivative_indicator_1===\n{trading_derivative_indicator_1[0]}")
for i in trading_derivative_indicator_1:
    # 流通市值
@@ -26,7 +26,7 @@
'''
衍生财务指标
'''
deriv_finance_indicator = get_fundamentals(table='deriv_finance_indicator', symbols='SZSE.000890', start_date=start_time_data, end_date=data_cache.DataCache.today_date, fields='FCFE, FCFF', df=False)
deriv_finance_indicator = get_fundamentals(table='deriv_finance_indicator', symbols='SZSE.000890', start_date=start_time_data, end_date=data_cache.DataCache().today_date, fields='FCFE, FCFF', df=False)
# print(f"deriv_finance_indicator===\n{deriv_finance_indicator[0]}")
for i in deriv_finance_indicator:
strategy/buying_strategy.py
@@ -8,11 +8,13 @@
# from datetime import time
# from datetime import timedelta
import time
import utils.tool
# import dateutil
# 引入掘金API
# from gm.api import *
from strategy import data_cache
from strategy import basic_methods
from strategy import account_management
from strategy import order_methods
from strategy.logging_config import get_logger
@@ -98,7 +100,7 @@
# 涨幅视界策略【根据涨幅进入视界为起始的策略】
def growth_view_strategy(context, current_info):
def growth_view_strategy(current_info):
    # 设定当前时间点
    # now_time = datetime.datetime.now().strftime("%H:%M:%S")
    symbol_code = current_info[0]  # 券商接口为纯数字编号
@@ -291,8 +293,7 @@
                                            logger.info(f"【不利】昨日跌停!不买!!")
                                        # elif k_line_data[0]['attribute'] == 'up_down' and k_line_data[0]['today_volume_shape'] == 'increases_down':
                                        #     logger.info(f"【不利】昨日高开低走 且 放量下跌,不买!!")
                                        elif k_line_data[0]['attribute'] == 'down_down' and k_line_data[0][
                                            'today_volume_shape'] == 'increases_down':
                                        elif k_line_data[0]['attribute'] == 'down_down' and k_line_data[0]['today_volume_shape'] == 'increases_down':
                                            logger.info(f"【不利】昨日低开低走 且 放量下跌,不买!!")
                                        elif throwing_pressure_position[0] is True:
                                            # 最近涨停日期:{k_line_data[limit_up_day_min_index]['bob']} ,
@@ -325,10 +326,11 @@
                                            logger.info(
                                                f"最新价: {current_price}, 当日最高价:{current_high},瞬时涨幅: {tick_growth:.2f}%,当日当时涨幅:{today_growth}%,公司名称:{k_line_data[0]['sec_name']},当前时间:{current_created_at},低于水位线:{deep_low:.2f},交易量今日与昨日的比例{round(current_volume / k_line_data[0]['volume'], 2)}")
                                            logger.info(
                                                f"大盘情绪分数:{data_cache.real_time_market_strong},设想的下单金额:{data_cache.have_plate_buy_money}")
                                            order_methods.buy_order_by_value(symbol, data_cache.have_plate_buy_money,
                                                f"大盘情绪分数:{data_cache.real_time_market_strong},设想的下单金额:{data_cache.today_planned_order_amount}")
                                            # 调用下单方法下单
                                            order_methods.buy_order_by_value(symbol, data_cache.today_planned_order_amount,
                                                                             k_line_data[0]['sec_name'],
                                                                             today_limit_up_price)
                                                                             current_price)
                                            # 将有概念买入次数自加1
                                            data_cache.have_plate_buy_times += 1
                                            # 将买入个股的当时概念添加到全局变量中存储
@@ -404,13 +406,15 @@
                                                    f"************************************************【有概念无强度指标下单】************************************************")
                                                logger.info(
                                                    f"最新价: {current_price}, 当日最高价:{current_high},瞬时涨幅: {tick_growth:.2f}%,当日当时涨幅:{today_growth}%,公司名称:{k_line_data[0]['sec_name']},当前时间:{current_created_at},低于水位线:{deep_low:.2f},交易量今日与昨日的比例{round(current_volume / k_line_data[0]['volume'], 2)}")
                                                # 调用下单方法下单
                                                order_methods.buy_order_by_value(symbol, 1000,
                                                                                 k_line_data[0]['sec_name'],
                                                                                 today_limit_up_price)
                                                                                 current_price)
                                                # 将有概念买入次数自加1
                                                data_cache.have_plate_buy_times += 1
                                                # 将买入个股的当时概念添加到全局变量中存储
                                                data_cache.bought_plate.extend(limit_up_plate_included_list)
                                '''
                                无概念 有强度视界
                                '''
@@ -485,11 +489,12 @@
                                                    logger.info(
                                                        f"最新价: {current_price}, 当日最高价:{current_high},瞬时涨幅: {tick_growth:.2f}%,当日当时涨幅:{today_growth}%,公司名称:{k_line_data[0]['sec_name']},当前时间:{current_created_at},低于水位线:{deep_low:.2f},交易量今日与昨日的比例{round(current_volume / k_line_data[0]['volume'], 2)}")  # 输出当前价格和3秒涨幅信息
                                                    logger.info(
                                                        f"大盘情绪分数:{data_cache.real_time_market_strong},设想的下单金额:{data_cache.have_strength_buy_money}")
                                                        f"大盘情绪分数:{data_cache.real_time_market_strong},设想的下单金额:{data_cache.today_planned_order_amount}")
                                                    # 调用下单方法下单
                                                    order_methods.buy_order_by_value(symbol,
                                                                                     data_cache.have_strength_buy_money,
                                                                                     data_cache.today_planned_order_amount,
                                                                                     k_line_data[0]['sec_name'],
                                                                                     today_limit_up_price)
                                                                                     current_price)
                                                    # 将有强度买入次数自加1
                                                    data_cache.have_strength_buy_times += 1
                                                    # 将买入个股的当时概念添加到全局变量中存储
@@ -583,9 +588,10 @@
                                                    logger.info(
                                                        f"目前获取的精选板块股票强度数据  ==  {data_cache.market_sift_plate_stock_dict}")
                                                    # buying_ratio = basic_methods.maximum_buying_ratio(len(data_cache.addition_position_symbols_set))
                                                    # 调用下单方法下单
                                                    order_methods.buy_order_by_value(symbol, 1000,
                                                                                     k_line_data[0]['sec_name'],
                                                                                     today_limit_up_price)
                                                                                     current_price)
                                                    # 将有小量换大涨幅买入次数自加1
                                                    data_cache.have_small_turn_large_buy_times += 1
                                                    # 将买入个股的当时概念添加到全局变量中存储
@@ -595,8 +601,7 @@
                                '''
                                if k_line_data[0]['attribute'] in data_cache.limit_up_type:
                                    # logger.info(f"昨日涨停")
                                    if k_line_data[1]['attribute'] not in data_cache.limit_up_type and k_line_data[2][
                                        'attribute'] not in data_cache.limit_up_type:
                                    if k_line_data[1]['attribute'] not in data_cache.limit_up_type and k_line_data[2]['attribute'] not in data_cache.limit_up_type:
                                        # logger.info(f"前日大前日未涨停")
                                        if today_open_growth > 1:
                                            logger.info(
@@ -688,13 +693,13 @@
                # print(f"now_end===={now_end}")
                # print(f"now_end type===={type(now_end)}")
                now_start_to_end = abs(created_at - now_end)
                logger.info(f"获取到判断花费==={now_start_to_end} 秒")
                logger.info(f"获取到判断花费==={round(now_start_to_end,2)} 秒")
                # print(f" now_end=={now_end}  created_at=={created_at}")
                # 设定一个时间阈值(比如9秒)
                threshold = datetime.timedelta(seconds=4)
                if now_start_to_end > threshold:
                threshold_4 = datetime.timedelta(seconds=4).total_seconds()
                if now_start_to_end > threshold_4:
                    logger.info(f"获取到判断花费大于4秒啦!!!")
                threshold_6 = datetime.timedelta(seconds=6)
                threshold_6 = datetime.timedelta(seconds=6).total_seconds()
                if now_start_to_end > threshold_6:
                    logger.info(f"获取到判断花费大于6秒啦!!!")
                logger.info(
strategy/check_timer.py
@@ -29,7 +29,7 @@
                kpl_api.get_arrange_limit_up_info()
                logger.info(f"整理当日涨停信息 已经运行完成")
                # # 获取所有个股的板块概念并写入文件【耗时较长应该放在 核心主线程 和 仓位管理 后面】
                kpl_api.get_all_stocks_plate_dict(data_cache.DataCache.filtered_stocks)
                kpl_api.get_all_stocks_plate_dict(data_cache.DataCache().filtered_stocks)
                logger.info(f"获取所有个股的板块概念 已经运行完成")
                # 完成了后将是否执行的开个标记为真
                data_cache.execution = True
strategy/data_cache.py
@@ -62,9 +62,7 @@
        '''
        设定基本时间点
        '''
        # 获取A股市场(包含沪深两市)的股票列表跳过停牌,跳过ST    上交所 SHSE.600000   深交所 SZSE.000000    target = ['SHSE.603839', 'SZSE.002855']
        # TODO 获取所有的票
        self.all_stocks = utils.juejin_api.JueJinApi.get_target_codes()
        # self.all_stocks = [{'sec_level': 1, 'symbol': 'SZSE.301633','pre_close': 78.72000122070312, 'is_suspended': 0, 'sec_name': '港迪技术', 'listed_date': datetime.datetime(2024, 11, 7, 0, 0,tzinfo=datetime.timezone(datetime.timedelta(seconds=28800))), 'sec_type': 1, 'sec_id': '301633'}]
@@ -83,11 +81,7 @@
        # self.filtered_stocks =  self.filtered_stocks[:10]
        print(f"过滤后上证A股和深证A股数量filtered_stocks:{len(self.filtered_stocks)}")
        # 获取上证A股和深证A股 基本信息
        # TODO 获取票的基本信息
        instruments = [stock for stock in self.all_stocks if stock['symbol'] in self.filtered_stocks]
        # instruments = get_instruments(symbols=self.filtered_stocks, exchanges=None, sec_types=None, names=None,
        #                               fields="symbol,sec_name,pre_close", df=False)
        # basic_info_symbols_dict = {}  # 初始化A股代码字典
        # 将获取到的上证A股和深证A股 基本信息 汇编为一个字典
        basic_info_symbols_dict = {}
        # 初始化没有K线的股票
@@ -111,14 +105,11 @@
        # 获取当前进程的PID
logging.info("全局初始化数据  开始》》》")
# 全局化上下文对象context
context = None
'''
设定基本时间点
'''
Local_startup_time = datetime.datetime.now().strftime("%H:%M:%S")
L1_data_start_time = datetime.time(9, 15, 00).strftime("%H:%M:%S")  # 定义9:15
before_open_bidding_time = datetime.time(9, 20, 00).strftime("%H:%M:%S")  # 定义9:20
open_bidding_time = datetime.time(9, 25, 00).strftime("%H:%M:%S")  # 定义 盘前 集合竞价 时间
later_open_bidding_time = datetime.time(9, 25, 30).strftime("%H:%M:%S")  # 定义 盘前 集合竞价 时间
@@ -188,16 +179,14 @@
current_new_price = 0
# 为当前账户全部【资金信息】创建字典
account_finance = {}
# 为当前账户可用资金赋初值
available = 0
account_finance_dict = {}
# 为当前账户全部【持仓信息】创建列表
account_positions = []
account_positions_dict = {}
# 为持仓代码创建一个初始集合
position_symbols_set = set()
# 为当日可用持仓代码创建一个初始集合
available_symbols_set = set()
# 为当日新增加持仓代码创建一个初始集合
# 为当日新增加持仓代码创建一个初始集合   买入策略中会用到 判断是否成功买了三支票
addition_position_symbols_set = set()
# 定义一个记录开盘价(开盘时最新价)是否记录
@@ -218,12 +207,16 @@
bought_plate = []
# 持仓金额自动管理开关
position_automatic_management_switch = True
# 初始化有概念买入仓位
# 初始化有概念买入金额
have_plate_buy_money = 3000
# 初始化有强度买入仓位
# 初始化有强度买入金额
have_strength_buy_money = 3000
# 今日计划下单金额
today_planned_order_amount = 0
# 最新的市场行情数据
# {"code":(代码,昨日收盘价,最新价,总成交量,总成交额,买五档(价格,成交额),卖五档(价格,成交额),更新时间)}
latest_code_market_info_dict = {}
logging.info(f"全局初始化数据  完成《《《 - {os.getpid()}")
strategy/instant_time_market.py
@@ -1,11 +1,13 @@
# 分时量分析,即情绪面(针对瞬时行情信息进行获取与分析)
# 计划将 current 和 subscribe(行情订阅) 线程 放在这里
# import json
import json
import logging
import time
import datetime
import utils
# 引入掘金API
# 引入华鑫API(小辉整理)
from strategy import l1_data_api
from strategy import data_cache
@@ -35,37 +37,37 @@
    # buying_strategy.growth_horizon_strategy(context, current_data)
    # selling_strategy.instantaneous_increase_strategy(context, current_data)
# 获取掘金current数据
def get_current_data():
    logging.info(f"get_current_data进入")
    while True:
        try:
            now_start = time.time()
            current_datas = current(symbols=data_cache.DataCache.min_stocks,
                                    fields='open,high,low,symbol,price,created_at,cum_volume,cum_amount,last_volume,quotes')
            # current_datas = l1_data_api.get_current_info()
            # print(f"l1_data_current_datas===={current_datas}")
            # print(f"current_datas====={current_datas}")
            now_end = time.time()
            now_start_to_end = now_end - now_start
            # index = 0
            for current_data in current_datas:
                # index+=1
                try:
                    __process(data_cache.context, current_data)
                    # if index == 100:
                    #     print(current_data)
                    # print(f"第几个{index}")
                except Exception as error:
                    logging.exception(error)
                    print("异常:", current_data)
            print(f"运行中=={round(now_start_to_end, 2)}秒")
            # logger.info(f"运行中=={round(now_start_to_end, 2)}秒")
        except Exception as error:
            logging.exception(error)
        finally:
            time.sleep(1)
#
# # 获取掘金current数据
# def get_current_data():
#     logging.info(f"get_current_data进入")
#     while True:
#         try:
#             now_start = time.time()
#             current_datas = current(symbols=data_cache.DataCache().min_stocks,
#                                     fields='open,high,low,symbol,price,created_at,cum_volume,cum_amount,last_volume,quotes')
#             # current_datas = l1_data_api.get_current_info()
#             # print(f"l1_data_current_datas===={current_datas}")
#             # print(f"current_datas====={current_datas}")
#             now_end = time.time()
#             now_start_to_end = now_end - now_start
#             # index = 0
#             for current_data in current_datas:
#                 # index+=1
#                 try:
#                     __process(data_cache.context, current_data)
#                     # if index == 100:
#                     #     print(current_data)
#                     # print(f"第几个{index}")
#                 except Exception as error:
#                     logging.exception(error)
#                     print("异常:", current_data)
#             print(f"运行中=={round(now_start_to_end, 2)}秒")
#             # logger.info(f"运行中=={round(now_start_to_end, 2)}秒")
#         except Exception as error:
#             logging.exception(error)
#         finally:
#             time.sleep(1)
"""
@@ -74,13 +76,12 @@
# 调用所有以current信息为核心策略的函数
def strategic_thread_manager(context, current_info):
def strategic_thread_manager(current_info):
    if current_info is not None:
        # 调用交易策略模块中的涨幅视界策略
        buying_strategy.growth_view_strategy(context, current_info)
        selling_strategy.instantaneous_change_strategy(context, current_info)
        buying_strategy.growth_view_strategy(current_info)
        selling_strategy.instantaneous_change_strategy(current_info)
        # pass
# 生成所有个股的开盘价字典
def get_all_stocks_current_open(current_infos):
@@ -113,14 +114,14 @@
                # logger.info(f"【没有】在集合竞价内启动,采用【掘金数据】记录")
                print(f"【没有】在开盘前内启动,采用【掘金数据】记录 开盘价")
                data_cache.record_current_open_execution = True
                current_datas = current(symbols=data_cache.DataCache.filtered_stocks, fields='symbol,open')
                current_datas = utils.juejin_api.JueJinApi.get_codes_open(data_cache.DataCache().filtered_stocks, fields='symbol,open')
                # print(f"current_datas=={current_datas}")
                for current_data in current_datas:
                    # print(f"current_data=={current_data}")
                    # 检查股票是否已经在data_cache中
                    # if current_data[0] not in data_cache.all_stocks_current_open:
                    data_cache.all_stocks_current_open[current_data['symbol']] = {'current_open': current_data['open']}
                # 将转换后的JSON字符串写入文件(目前考虑取消数据存储本地)
                # 将转换后的JSON字符串写入文件(目前取消数据存储本地,如需存储本地也要放在D:盘路径)
                # with open('local_storage_data/all_stocks_current_open.json', 'w', encoding='utf-8') as f:
                #     # 将字典转换为 JSON 格式的字符串
                #     json_data = json.dumps(data_cache.all_stocks_current_open, ensure_ascii=False, indent=4)
@@ -224,7 +225,9 @@
            # print(f"当前时间更新时间:{now_time}")
            if not __current_high_or_low_dict:
                # 还没初始化
                current_datas = current(symbols=data_cache.DataCache.filtered_stocks, fields='symbol,high,low')
                # current_datas = current(symbols=data_cache.DataCache().filtered_stocks, fields='symbol,high,low')
                current_datas = utils.juejin_api.JueJinApi.get_codes_high_and_low(
                    data_cache.DataCache().filtered_stocks, fields='symbol,high,low')
                # print(f"current_datas=={current_datas}")
                for current_data in current_datas:
                    symbol, high, low = current_data['symbol'], current_data['high'], current_data['low']
@@ -234,7 +237,7 @@
            for current_info in current_infos:
                # print(f"开始循环current_infos")
                symbol = basic_methods.format_stock_symbol(current_info[0])
                if symbol not in data_cache.DataCache.filtered_stocks:
                if symbol not in data_cache.DataCache().filtered_stocks:
                    continue
                # if symbol.find("300810") > 0:
                #     print(f"开始循环current_infos:"+symbol)
@@ -243,7 +246,9 @@
                price_track_manage = __current_high_or_low_dict.get(symbol)
                if not price_track_manage:
                    # 初始化
                    current_datas = current(symbols=[symbol], fields='symbol,high,low')
                    # current_datas = current(symbols=[symbol], fields='symbol,high,low')
                    current_datas = utils.juejin_api.JueJinApi.get_codes_high_and_low(
                        data_cache.DataCache().filtered_stocks, fields='symbol,high,low')
                    current_data = current_datas[0]
                    # print(f"开始实例化对象")
                    symbol, high, low = current_data['symbol'], current_data['high'], current_data['low']
@@ -258,7 +263,6 @@
                        'current_high': price_track_manage.current_high,
                        'current_low': price_track_manage.current_low}
                    # print(f"data_cache.all_stocks_current_high_and_low[symbol]==={data_cache.all_stocks_current_high_and_low[symbol]}")
            # print(f"完成华鑫初始化:{now_time}")
# 构建获取个股记录下来的实时当日最高价函数
@@ -277,25 +281,73 @@
        return None
def process_current_infos(current_infos):
    """
    处理现价
    :param current_infos:
    :return:
    """
# def process_current_infos():
#     """
#     处理现价
#     :param current_infos:
#     :return:
#     """
#     while True:
#         try:
#             now_start = time.time()
#             current_infos = l1_data_api.get_current_info()
#             now_time = datetime.datetime.now().strftime("%H:%M:%S")
#             if len(current_infos) == 0 and now_time > data_cache.L1_data_start_time:
#                 print(f"9:15后 l1数据为空=l1_data_current_infos===={current_infos}")
#             for i in current_infos:
#                 if i[0] == '000001':
#                     print(f"i===={i}")
#
#
#             get_all_stocks_current_open(current_infos)
#             get_all_stocks_current_high_and_low(current_infos)
#             for current_info in current_infos:
#                 try:
#                     if current_info is not None:
#                         strategic_thread_manager(current_info)
#                 except Exception as error:
#                     logging.exception(error)
#                     print("异常:", current_info)
#             now_end: float = time.time()
#             start_to_end = now_end - now_start
#             print(f"运行中=={round(start_to_end, 2)} 秒")
#             # logger.info(f"运行中=={round(start_to_end, 2)}秒")
#         except Exception as error:
#             logging.exception(error)
#         finally:
#             time.sleep(0.5)
def get_current_info():
    logging.info(f"get_current_info进入")
    # shm = SharedMemoryObj(name="l1_data_shared_memory", size=5 * 1024 * 1024)
    while True:
        try:
    now_start = time.time()
            current_infos = l1_data_api.get_current_info()
            now_time = datetime.datetime.now().strftime("%H:%M:%S")
            if len(current_infos) == 0 and now_time > data_cache.L1_data_start_time:
                print(f"9:15后 l1数据为空=l1_data_current_infos===={current_infos}")
            # for i in current_infos:
            #     if i[0] == '000001':
            #         print(f"i===={i}")
    get_all_stocks_current_open(current_infos)
    get_all_stocks_current_high_and_low(current_infos)
    for current_info in current_infos:
        try:
            if current_info is not None:
                strategic_thread_manager(None, current_info)
                        strategic_thread_manager(current_info)
        except Exception as error:
            logging.exception(error)
            print("异常:", current_info)
                    # print("异常:", current_info)
    now_end: float = time.time()
    start_to_end = now_end - now_start
    print(f"运行中=={round(start_to_end, 2)} 秒")
            # logger.info(f"运行中=={round(start_to_end, 2)}秒")
        except Exception as error:
            logging.exception(error)
        finally:
            time.sleep(0.5)
strategy/kpl_api.py
@@ -213,8 +213,8 @@
    data = (getMarketJingXuanRealRankingInfo())
    market_sift_plate = json.loads(data)
    # print(f"market_sift_plate 数 ======{len(market_sift_plate['list'])}")
    logger.info(f"market_sift_plate['list']======{market_sift_plate['list']}")
    logger.info(f"market_sift_plate['list'][0]  ======{market_sift_plate['list'][0]}")
    # logger.info(f"market_sift_plate['list']======{market_sift_plate['list']}")
    # logger.info(f"market_sift_plate['list'][0]  ======{market_sift_plate['list'][0]}")
    # 初始化精选板块对应个股字典
    market_sift_plate_stock_dict = {}
    if 'list' in market_sift_plate:
@@ -328,7 +328,7 @@
        # print(f"json_data=={json_data}")
        if len(json_data) != 0:
            # 写入文件
            with open('local_storage_data/limit_up_block_names.json', 'w', encoding='utf-8') as f:
            with open(constant.KPL_LIMIT_UP_BLOCK_NAMES_PATH, 'w', encoding='utf-8') as f:
                f.write(json_data)
    return limit_up_block_names
@@ -378,7 +378,7 @@
                        # 打开文件并追加JSON行
                        with open(self.file_path, 'a', encoding='utf-8') as file:file.write(json_line)
                    else:
                        print(f"(当日日期已存在于文件的最后一行了,不再重复追加写入)")
                        logger.info(f"(当日日期已存在于文件的最后一行了,不再重复追加写入)")
                else:
                    json_line = json.dumps({current_date: data_to_append}, ensure_ascii=False) + '\n'
                    # 打开文件并追加JSON行
@@ -702,22 +702,26 @@
                data_cache.real_time_market_strong = get_market_strong()
                # data_cache.time_sharing_market_strong_dirt = time_sharing_market_strong_dirt.update({now: data_cache.real_time_market_strong})
                logger.info(f"大盘行情情绪综合强度 [分数]==={data_cache.real_time_market_strong}分")
                # 机械版
                # if data_cache.real_time_market_strong >= 70:
                #     data_cache.have_plate_buy_money = 30000
                #     data_cache.have_strength_buy_money = 30000
                # elif 60 <= data_cache.real_time_market_strong < 70:
                #     data_cache.have_plate_buy_money = 20000
                #     data_cache.have_strength_buy_money = 20000
                # elif 50 <= data_cache.real_time_market_strong < 60:
                #     data_cache.have_plate_buy_money = 10000
                #     data_cache.have_strength_buy_money = 10000
                # elif 30 <= data_cache.real_time_market_strong < 50:
                #     data_cache.have_plate_buy_money = 3000
                #     data_cache.have_strength_buy_money = 3000
                # elif data_cache.real_time_market_strong < 30:
                #     data_cache.have_plate_buy_money = 1000
                #     data_cache.have_strength_buy_money = 1000
                if data_cache.real_time_market_strong >= 70:
                    data_cache.have_plate_buy_money = 30000
                    data_cache.have_strength_buy_money = 30000
                elif 60 <= data_cache.real_time_market_strong < 70:
                    data_cache.have_plate_buy_money = 20000
                    data_cache.have_strength_buy_money = 20000
                elif 50 <= data_cache.real_time_market_strong < 60:
                    data_cache.have_plate_buy_money = 10000
                    data_cache.have_strength_buy_money = 10000
                elif 30 <= data_cache.real_time_market_strong < 50:
                    data_cache.have_plate_buy_money = 3000
                    data_cache.have_strength_buy_money = 3000
                elif data_cache.real_time_market_strong < 30:
                    data_cache.have_plate_buy_money = 1000
                    data_cache.have_strength_buy_money = 1000
                # 根据账户可用金额 计算今日计划下单金额
                # (账户可用金额/今日最大新增持仓票数) * (大盘综合强度份数 * 0.01)
                data_cache.today_planned_order_amount = (data_cache.account_finance_dict['usefulMoney'] / 3) * (data_cache.real_time_market_strong * 0.01)
        except Exception as error:
            logger.error(f"获取实时大盘行情情绪综合强度[分数] 函数报错: {error}")
        finally:
strategy/message_analysis.py
@@ -1 +1,2 @@
# 消息分析,即消息面分析
strategy/order_methods.py
@@ -1,31 +1,46 @@
"""
 交易方式模块(总览处理所有渠道的各种交易方法集合)
"""
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
# 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, huaxin_trade_data_update, middle_api_protocol
from utils import huaxin_util
# 获取logger实例
logger = get_logger()
# 下单买入函数(按金额,以限价买)【按金额买 基础版】
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):
    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}】")
    if volume < 100:
        volume = 100
    # 调用笼子价计算工具计算下单价格
    order_price = tool.get_buy_max_price(current_price)
    buy_order = huaxin_trade_api.order(1, symbol[-6:], volume, order_price, blocking=True)
    logger.info(f"buy_order===={buy_order}")
    orderStatusMsg = buy_order['data'].get('orderStatusMsg', None)
    statusMsg = buy_order['data'].get('statusMsg', None)
    # orderStatusMsg 不在buy_order的下单回调中,那么才认为下单成功
    if orderStatusMsg is not None or (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}")
    # 买票后添加 持仓代码集合
    data_cache.position_symbols_set.add(symbol)
    # 买票后添加 今日新增持仓代码集合
@@ -51,7 +66,7 @@
    # 只有持仓数量大于委卖数量才进入买票流程
    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)}")
@@ -60,152 +75,73 @@
# 下单卖出函数(按持仓数量,在限价卖)【按量卖 基础版】
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):
    # 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"sell_order===={sell_order}")
    orderStatusMsg = sell_order['data'].get('orderStatusMsg', None)
    statusMsg = sell_order['data'].get('statusMsg', None)
    # orderStatusMsg 不在buy_order的下单回调中,那么才认为下单成功
    if orderStatusMsg is not None or (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():
strategy/selling_strategy.py
@@ -93,11 +93,12 @@
# 分时变化策略
def instantaneous_change_strategy(context, current_info):
def instantaneous_change_strategy(current_info):
    # 设定当前时间点
    now_time = datetime.datetime.now().strftime("%H:%M:%S")
    symbol_code = current_info[0]  # 券商接口为纯数字编号
    symbol = basic_methods.format_stock_symbol(symbol_code)  # 掘金数据来源的股票代码
    # symbol = symbol_code
    symbol = basic_methods.format_stock_symbol(symbol_code)  # 转化为掘金数据来源的股票代码
    # symbol_code = symbol.split('.')[1]  # 将掘金格式的股票代码转化为纯数字类型
    # print(f"symbol==={symbol}")
    pre_close = current_info[1]  # 昨日收盘价
@@ -122,20 +123,25 @@
    #     f"卖一量:{current_quotes_sell[0][1]},买二量:{current_quotes_sell[1][1]},买三量:{current_quotes_sell[2][1]},买四量:{current_quotes_sell[3][1]},买五量:{current_quotes_sell[4][1]}")
    # 如果在持仓可用里面有 当前current_data循环到的个股tick 就开始做具体的逻辑判断
    # print(f"data_cache.account_positions=={data_cache.account_positions}")
    # import test
    # test_data = test.test_data
    for index, element in enumerate(data_cache.account_positions):
        if element['symbol'] == symbol:  # 当循环到的持仓代码正好是current_data的代码时,即取得了持仓个股的行情快照数据
    # :return: {'code': 0, 'data': [{'investorID': '00044396', 'tradingDay': '20250109', 'securityName': '海得控制', 'securityID': '002184', 'historyPos': 0, 'historyPosFrozen': 0, 'todayBSPos': 1000, 'todayBSPosFrozen': 0, 'historyPosPrice': 0.0, 'totalPosCost': 20316.176271, 'prePosition': 0, 'availablePosition': 0, 'currentPosition': 1000, 'openPosCost': 20310.0, 'todayCommission': 6.176271, 'todayTotalBuyAmount': 20310.0, 'todayTotalSellAmount': 0.0}, {'investorID': '00044396', 'tradingDay': '20250109', 'securityName': '省广集团', 'securityID': '002400', 'historyPos': 0, 'historyPosFrozen': 0, 'todayBSPos': 0, 'todayBSPosFrozen': 0, 'historyPosPrice': 0.0, 'totalPosCost': 0.0, 'prePosition': 0, 'availablePosition': 0, 'currentPosition': 0, 'openPosCost': 0.0, 'todayCommission': 0.0, 'todayTotalBuyAmount': 8230.0, 'todayTotalSellAmount': 0.0}]}
    # print(f"data_cache.account_positions_dict==={data_cache.account_positions_dict}")
    if data_cache.account_positions_dict is not None:
        for index, element in enumerate(data_cache.account_positions_dict):
            # print(f"index=={index}")
            # print(f"element=={element}")
            element_symbol = basic_methods.format_stock_symbol(element['securityID'])
            if symbol_code == element['securityID']:  # 当循环到的持仓代码正好是current_data的代码时,即取得了持仓个股的行情快照数据
            # logger.info(f"index = {index}")
            # logger.info(f"element = {element}")
            account_positions_symbol = element['symbol']  # 当前循环到的持仓个股代码
                account_positions_symbol = element_symbol  # 当前循环到的持仓个股代码
            # print(f"account_positions_symbol==={account_positions_symbol}")
            # available_now = element['available_now']  # 当前个股可用金额
            # price = d['price']   #当前行情价,,,非最新价,没有实际意义不要用!!!
            vwap = element['vwap']  # 当前个股持仓均价/成本价
            position_volume = element['volume']  # 当前个股持仓量
            position_volume_today = element['volume_today']  # 今日持仓量
            position_volume_yesterday = position_volume - position_volume_today  # 昨日持仓量(可用持仓量)
                vwap = element['historyPosPrice']  # 当前个股持仓均价/成本价
                position_volume = element['currentPosition']  # 当前个股持仓总量
                position_volume_today = element['todayTotalBuyAmount']  # 今日持仓量
                position_volume_yesterday = element['availablePosition']  # 股份可用 (可用股份数量)  # 昨日持仓量(可用持仓量)
            # print(symbol,available_now, price, vwap)
            # print(f"current_open=={current_open}")
            # print(f"current_price=={current_price}")
@@ -187,8 +193,7 @@
                    '''
                    集合竞价阶段决断(只判断一次)
                    '''
                    if data_cache.after_open_bidding_time < now_time < data_cache.opening_time and data_cache.execution_times < len(
                            data_cache.available_symbols_set):
                        if data_cache.after_open_bidding_time < now_time < data_cache.opening_time and data_cache.execution_times < len(data_cache.available_symbols_set):
                        # 每进入该条件分支一次就把进入次数自加1
                        data_cache.execution_times += 1
                        logger.info(f"这个分支逻辑已经执行次数:{data_cache.execution_times}")
@@ -202,7 +207,7 @@
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日起飞失败】【浮盈】【低开】,低开:{today_open_growth}%,设定委卖数量【十分之一仓】")
                                    order_methods.sell_order_by_part_volume(0.1, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'],
                                                                            index)
                            if floating_profit_and_loss <= 0:
@@ -211,14 +216,14 @@
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日起飞失败】【浮亏】【中高开/大高开】,高开:{today_open_growth}%,设定委卖数量【十分之五仓】")
                                    order_methods.sell_order_by_part_volume(0.5, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 小高开视界
                                if 4 > today_open_growth >= 1:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日起飞失败】【浮亏】【小高开】,高开:{today_open_growth}%,设定委卖数量【十分之三仓】")
                                    order_methods.sell_order_by_part_volume(0.3, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'],
                                                                            index)
                                # 平开视界 +- 1
@@ -226,7 +231,7 @@
                                    logger.info(
                                        f"【集合竞价】【平开】【{k_line_data[0]['sec_name']}】【昨日起飞失败】【浮亏】【平开】,平开:{today_open_growth}%,设定委卖数量【十分之五仓】")
                                    order_methods.sell_order_by_part_volume(0.5, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'],
                                                                            index)
                                # 低开视界
@@ -234,7 +239,7 @@
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日起飞失败】【浮亏】【小低开】,低开:{today_open_growth}%,设定委卖数量【全仓】")
                                    order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                        # 昨日涨停视界
                        if k_line_data[0]['attribute'] in data_cache.limit_up_type:
@@ -252,14 +257,14 @@
                                        logger.info(
                                            f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日涨停】【浮亏】【小低开】,低开:{today_open_growth}%,设定委卖数量【十分之五仓】")
                                        order_methods.sell_order_by_part_volume(0.5, symbol, position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'], index)
                                    # 中低开/大低开视界
                                    if today_open_growth <= -4:
                                        logger.info(
                                            f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日涨停】【浮亏】【中低开/大低开】,低开:{today_open_growth}%,设定委卖数量【全仓】")
                                        order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'], index)
                            #  如果昨日集合竞价最后时刻炸板的股票【开盘啦昨日炸板但通过K线数据计算涨停的股票代码列表】
                            if symbol in data_cache.yesterday_frying_plate_last_minute_list:
@@ -268,7 +273,7 @@
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日K线涨停,开盘啦炸板】【非触摸板状态】,开盘涨幅:{today_open_growth}%,设定委卖数量【全仓】")
                                    order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                        # 昨日炸板视界
                        if k_line_data[0]['attribute'] in data_cache.frying_plate_type:
@@ -278,35 +283,35 @@
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮盈】【中高开/大高开】,高开:{today_open_growth}%,设定委卖数量【二十分之一仓】")
                                    order_methods.sell_order_by_part_volume(0.05, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 小高开视界
                                if 4 > today_open_growth >= 1:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮盈】【小高开】,高开:{today_open_growth}%,设定委卖数量【十分之一仓】")
                                    order_methods.sell_order_by_part_volume(0.1, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 平开视界 < ±1%
                                if -1 < today_open_growth < 1:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮盈】【平开】,平开:{today_open_growth}%,设定委卖数量【十分之五仓】")
                                    order_methods.sell_order_by_part_volume(0.5, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 小低开视界
                                if -4 < today_open_growth <= -1:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮盈】【小低开】,低开:{today_open_growth}%,设定委卖数量【十分之七仓】")
                                    order_methods.sell_order_by_part_volume(0.7, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 中低开/大低开视界
                                if today_open_growth <= -4:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【中低开/大低开】,低开:{today_open_growth}%,设定委卖数量【全仓】")
                                    order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                            if floating_profit_and_loss <= 0:
@@ -315,42 +320,42 @@
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮亏】【中高开/大高开】,高开:{today_open_growth}%,设定委卖数量【十分之二仓】")
                                    order_methods.sell_order_by_part_volume(0.2, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 小高开视界
                                if 4 > today_open_growth >= 1:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮亏】【小高开】,高开:{today_open_growth}%,设定委卖数量【十分之五仓】")
                                    order_methods.sell_order_by_part_volume(0.5, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 平开视界 < ±1%
                                if -1 < today_open_growth < 1:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮亏】【平开】,平开:{today_open_growth}%,设定委卖数量【十分之五仓】")
                                    order_methods.sell_order_by_part_volume(0.5, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 小低开视界
                                if -4 < today_open_growth <= -1:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮亏】【小低开】,低开:{today_open_growth}%,设定委卖数量【十分之七仓】")
                                    order_methods.sell_order_by_part_volume(0.7, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                                # 中低开/大低开视界
                                if today_open_growth <= -4:
                                    logger.info(
                                        f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日炸板】【浮亏】【中低开/大低开】,低开:{today_open_growth}%,设定委卖数量【全仓】")
                                    order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                            today_limit_down_price,
                                                                                current_price,
                                                                            k_line_data[0]['sec_name'], index)
                        # 昨日跌停视界
                        if k_line_data[0]['attribute'] in data_cache.limit_down_type:
                            logger.info(
                                f"【集合竞价】【{k_line_data[0]['sec_name']}】【昨日跌停】【无论开盘涨幅多少!!!】,开盘涨幅:{today_open_growth}%,设定委卖数量【全仓】")
                            order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                    today_limit_down_price,
                                                                        current_price,
                                                                    k_line_data[0]['sec_name'], index)
                    '''
@@ -368,13 +373,13 @@
                                        logger.info(
                                            f"【开盘临机】【浮动盈亏当前亏】【瞬时跌幅 <-0.1%】【当日新低】【{k_line_data[0]['sec_name']}】,设定委卖数量【十分之一仓】,【瞬时跌幅:{round(tick_growth, 2)}%】,当日当时涨幅:{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                        order_methods.sell_order_by_part_volume(0.1, symbol, position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'], index)
                                    if tick_growth < -0.1 and today_growth < 0 and current_price <= current_low:
                                        logger.info(
                                            f"【开盘临机】【浮动盈亏当前亏】【瞬时跌幅 <-1%】【当日当时涨幅 <0%】【当日新低】【{k_line_data[0]['sec_name']}】,设定委卖数量【全仓】,【瞬时跌幅:{round(tick_growth, 2)}%】,当日当时涨幅:{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                        order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'], index)
                            # 昨日涨停视界
                            if k_line_data[0]['attribute'] in data_cache.limit_up_type:
@@ -385,7 +390,7 @@
                                            f"【开盘临机】【浮动盈亏当前亏】【瞬时跌幅 <-1%】【当日当时涨幅 <-4%】【{k_line_data[0]['sec_name']}】,设定委卖数量【十分之一仓】,【瞬时跌幅:{round(tick_growth, 2)}%】,当日当时涨幅:{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                        order_methods.sell_order_by_part_volume(0.1, symbol,
                                                                                position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'],
                                                                                index)
                                    if tick_growth < -0.1 and today_growth < 0 and current_price <= current_low:
@@ -393,7 +398,7 @@
                                            f"【开盘临机】【浮动盈亏当前亏】【瞬时跌幅 <-1%】【当日当时涨幅小于0%】【当日新低】【{k_line_data[0]['sec_name']}】,设定委卖数量【全仓】,【瞬时跌幅:{round(tick_growth, 2)}%】,当日当时涨幅:{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                        order_methods.sell_order_by_part_volume(1, symbol,
                                                                                position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'],
                                                                                index)
                            # 昨日炸板视界
@@ -403,7 +408,7 @@
                                    if tick_growth < -1 and today_growth < 0 and current_price <= current_low:
                                        order_methods.sell_order_by_part_volume(1, symbol,
                                                                                position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'],
                                                                                index)
                                # 浮动盈亏【亏】
@@ -413,7 +418,7 @@
                                            f"【开盘临机】【浮动盈亏当前亏】【瞬时跌幅 <-0.1%】【当日新低】【{k_line_data[0]['sec_name']}】,设定委卖数量【十分之一仓】,【瞬时跌幅:{round(tick_growth, 2)}%】,当日当时涨幅:{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                        order_methods.sell_order_by_part_volume(0.1, symbol,
                                                                                position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'],
                                                                                index)
                                    if tick_growth < -0.1 and today_growth < 0 and current_price <= current_low:
@@ -421,7 +426,7 @@
                                            f"【开盘临机】【浮动盈亏当前亏】【瞬时跌幅 <-1%】【当日当时涨幅小于0%】【当日新低】【{k_line_data[0]['sec_name']}】,设定委卖数量【全仓】,【瞬时跌幅:{round(tick_growth, 2)}%】,当日当时涨幅:{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                        order_methods.sell_order_by_part_volume(1, symbol,
                                                                                position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'],
                                                                                index)
                            # 昨日跌停视界
@@ -441,12 +446,12 @@
                                    if current_volume < k_line_data[0]['volume'] * 0.6:
                                        logger.info(
                                            f"【开盘临机】【 炸板!!且当日量不足】【{k_line_data[0]['sec_name']}】 买盘小于1万 且 今日量小于昨日量的 0.6,设定委卖数量【十分之一仓】,当日当时量:{current_volume}")
                                        # # 设定委卖数量【十分之一仓】
                                        # order_methods.sell_order_by_part_volume(0.1, symbol,
                                        #                                         position_volume_yesterday,
                                        #                                         today_limit_down_price,
                                        #                                         k_line_data[0]['sec_name'],
                                        #                                         index)
                                            # 设定委卖数量【十分之一仓】
                                            order_methods.sell_order_by_part_volume(0.1, symbol,
                                                                                    position_volume_yesterday,
                                                                                    current_price,
                                                                                    k_line_data[0]['sec_name'],
                                                                                    index)
                                else:
                                    logger.info(f"【开盘临机】【{k_line_data[0]['sec_name']}】 涨停封板!!")
                                # 如果 卖一 量 为零
@@ -457,28 +462,28 @@
                                    if current_volume < k_line_data[0]['volume'] * 0.6:
                                        logger.info(
                                            f"【开盘临机】【 炸板中!!且当日量不足】【{k_line_data[0]['sec_name']}】 卖一数量不等于0,设定委卖数量【十分之一仓】,当日当时量:{current_volume}")
                                        # order_methods.sell_order_by_part_volume(0.1, symbol,
                                        #                                         position_volume_yesterday,
                                        #                                         today_limit_down_price,
                                        #                                         k_line_data[0]['sec_name'],
                                        #                                         index)
                                            order_methods.sell_order_by_part_volume(0.1, symbol,
                                                                                    position_volume_yesterday,
                                                                                    current_price,
                                                                                    k_line_data[0]['sec_name'],
                                                                                    index)
                                    # 如果 卖二 量炸出来了,那么就是彻底炸开了。
                                    if current_quotes_sell[1][1] != 0:
                                        logger.info(
                                            f"【开盘临机】【 炸板炸开了!!】【{k_line_data[0]['sec_name']}】 卖二数量不等于0,设定委卖数量【十分之二仓】,当日当时量:{current_volume}")
                                        # order_methods.sell_order_by_part_volume(0.2, symbol,
                                        #                                         position_volume_yesterday,
                                        #                                         today_limit_down_price,
                                        #                                         k_line_data[0]['sec_name'],
                                        #                                         index)
                                            order_methods.sell_order_by_part_volume(0.2, symbol,
                                                                                    position_volume_yesterday,
                                                                                    current_price,
                                                                                    k_line_data[0]['sec_name'],
                                                                                    index)
                                        if current_volume < k_line_data[0]['volume'] * 0.8:
                                            logger.info(
                                                f"【开盘临机】【 炸板!!且当日量不足】【{k_line_data[0]['sec_name']}】 买盘小于1万 且 今日量小于昨日量的 0.8,设定委卖数量【全仓】,当日当时量:{current_volume}")
                                            # order_methods.sell_order_by_part_volume(1, symbol,
                                            #                                         position_volume_yesterday,
                                            #                                         today_limit_down_price,
                                            #                                         k_line_data[0]['sec_name'],
                                            #                                         index)
                                                order_methods.sell_order_by_part_volume(1, symbol,
                                                                                        position_volume_yesterday,
                                                                                        current_price,
                                                                                        k_line_data[0]['sec_name'],
                                                                                        index)
                        # 当前时间超过午盘时间【午盘决策】
                        if now_time > data_cache.noon_market_time:
@@ -490,7 +495,7 @@
                                        logger.info(
                                            f"【午盘决策】【昨日涨停】【当日未涨停 或 当日当时涨幅小于7%】【{k_line_data[0]['sec_name']}】 设定委卖数量【十分之五仓】,当日当时涨幅为{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                        order_methods.sell_order_by_part_volume(0.5, symbol, position_volume_yesterday,
                                                                                today_limit_down_price,
                                                                                    current_price,
                                                                                k_line_data[0]['sec_name'], index)
                        # 当前时间超过平仓时间【尾盘决断】
                        if now_time > data_cache.close_position_time:
@@ -498,6 +503,6 @@
                                logger.info(
                                    f"【尾盘决断】【当日未涨停 或 当日当时涨幅小于7%】【{k_line_data[0]['sec_name']}】 设定委卖数量【全仓】,当日当时涨幅为{today_growth}。最新价::{current_price},昨日收盘价:{k_line_data[0]['close']}")
                                order_methods.sell_order_by_part_volume(1, symbol, position_volume_yesterday,
                                                                        today_limit_down_price,
                                                                            current_price,
                                                                        k_line_data[0]['sec_name'], index)
strategy/shared_memory_util.py
File was deleted
strategy/subscribe_market.py
File was deleted
trade/huaxin_trade_api.py
@@ -425,8 +425,7 @@
    :param recancel:
    :return:
    """
    if tool.trade_time_sub(tool.get_now_time_str(), "14:57:00") >= 0 and tool.trade_time_sub(tool.get_now_time_str(),
                                                                                             "15:00:01") <= 0:
    if tool.trade_time_sub(tool.get_now_time_str(), "14:57:00") >= 0 and tool.trade_time_sub(tool.get_now_time_str(),"15:00:01") <= 0:
        # 集合竞价不撤单
        return
@@ -490,7 +489,7 @@
                           {"type": ClientSocketManager.CLIENT_TYPE_DEAL_LIST})
    return __read_response(request_id, blocking, timeout=timeout)
# todo 获取华鑫持仓列表 后续即可实现仓位管理
# 获取持仓列表
def get_position_list(blocking=True):
    """
@@ -502,7 +501,7 @@
                           {"type": ClientSocketManager.CLIENT_TYPE_POSITION_LIST})
    return __read_response(request_id, blocking)
# todo 获取华鑫账户资金 后续即可实现账户管理
# 获取账户资金状况
def get_money(blocking=True):
    """
@@ -514,6 +513,9 @@
                           {"type": ClientSocketManager.CLIENT_TYPE_MONEY})
    return __read_response(request_id, blocking)
# money = get_money()
# print(f"money=={money}")
# 设置L2订阅数据
def __test_trade_channel(sid):
utils/juejin_api.py
@@ -38,6 +38,10 @@
                             {"exchanges": exchanges, "sec_types": sec_types, "skip_suspended": skip_suspended,
                              "skip_st": skip_st, "fields": fields})
    @classmethod
    def current(cls, symbols, fields):
        return cls.__request("current", {"symbols": symbols, "fields": fields})
class JueJinApi:
    # 获取交易所的代码
@@ -54,7 +58,7 @@
        获取目标代码
        :return:
        """
        datas = JueJinApi.get_exchanges_codes(["SHSE", "SZSE"])
        datas = cls.get_exchanges_codes(["SHSE", "SZSE"])
        fdatas = []
        for d in datas:
            if d["sec_level"] != 1:
@@ -62,12 +66,33 @@
            fdatas.append(d)
        return fdatas
    # 获取目标股票范围内的开盘价
    @classmethod
    def get_codes_open(cls, symbols, fields):
        current = JueJinHttpApi.current(symbols, fields)
        # print(f"current=={current}")
        # current_datas==[{'symbol': 'SZSE.001288', 'open': 30.27, 'high': 31.77, 'low': 30.27, 'price': 30.77, 'quotes': [{'bid_p': 30.77, 'bid_v': 500, 'ask_p': 30.78, 'ask_v': 3900}, {'bid_p': 30.76, 'bid_v': 800, 'ask_p': 30.79, 'ask_v': 3100}, {'bid_p': 30.75, 'bid_v': 21900, 'ask_p': 30.8, 'ask_v': 22100}, {'bid_p': 30.72, 'bid_v': 1300, 'ask_p': 30.82, 'ask_v': 300}, {'bid_p': 30.7, 'bid_v': 600, 'ask_p': 30.83, 'ask_v': 2700}], 'cum_volume': 2586914, 'cum_amount': 80020708.18, 'trade_type': 8, 'created_at': datetime.datetime(2025, 2, 12, 14, 50, 18, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))}]
        return current
    # 获取目标股票范围内的日内实时最高价和最低价
    @classmethod
    def get_codes_high_and_low(cls, symbols, fields):
        current = JueJinHttpApi.current(symbols, fields)
        # print(f"current=={current}")
        # current_datas==[{'symbol': 'SZSE.001288', 'open': 30.27, 'high': 31.77, 'low': 30.27, 'price': 30.77, 'quotes': [{'bid_p': 30.77, 'bid_v': 500, 'ask_p': 30.78, 'ask_v': 3900}, {'bid_p': 30.76, 'bid_v': 800, 'ask_p': 30.79, 'ask_v': 3100}, {'bid_p': 30.75, 'bid_v': 21900, 'ask_p': 30.8, 'ask_v': 22100}, {'bid_p': 30.72, 'bid_v': 1300, 'ask_p': 30.82, 'ask_v': 300}, {'bid_p': 30.7, 'bid_v': 600, 'ask_p': 30.83, 'ask_v': 2700}], 'cum_volume': 2586914, 'cum_amount': 80020708.18, 'trade_type': 8, 'created_at': datetime.datetime(2025, 2, 12, 14, 50, 18, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))}]
        return current
if __name__ == '__main__':
    # 获取目标代码(获取目标票)
    print(JueJinApi.get_exchanges_codes(["SHSE", "SZSE"]))
    # print(f"JueJinApi.get_exchanges_codes==={JueJinApi.get_exchanges_codes(['SHSE', 'SZSE'])}")
    symbols = ['SZSE.001288', 'SZSE.000042']
    fields = 'symbol,open'
    # JueJinApi.get_codes_open(symbols, fields)
    #
    strategy.data_cache.all_stocks = JueJinApi.get_exchanges_codes(["SHSE", "SZSE"])
    print(len(JueJinApi.get_exchanges_codes(["SHSE", "SZSE"])))
    # strategy.data_cache.all_stocks = JueJinApi.get_exchanges_codes(["SHSE", "SZSE"])
    # current = JueJinHttpApi.current(symbols, fields)
    # print(current)
    # print(f"JueJinApi.get_exchanges_codes(['SHSE', 'SZSE'])=={len(JueJinApi.get_exchanges_codes(['SHSE', 'SZSE']))}")
utils/tool.py
@@ -281,7 +281,8 @@
# 获取买入价格笼子的最低价
def get_buy_min_price(price, is_cb=False):
    price1 = price * (1 - 0.02)
    # price1 = price * (1 - 0.015)  # 服务器版
    price1 = price * (1 - 0.005)  # 本地版
    if is_cb:
        price1 = math.ceil(price1 * 1000) / 1000
    else:
@@ -293,8 +294,10 @@
        return min(price1, price2)
# 获取买入价格笼子的最高价
def get_buy_max_price(price, is_cb=False):
    price1 = price * (1 + 0.02)
    # price1 = price * (1 + 0.015)  # 服务器版
    price1 = price * (1 + 0.005)  # 本地版
    if is_cb:
        price1 = math.ceil(price1 * 1000) / 1000
    else:
@@ -356,6 +359,18 @@
        return 0.9
    else:
        return 0.8
def get_limit_up_price(code, pre_price):
    price = (decimal.Decimal(pre_price) * decimal.Decimal(get_limit_up_rate(code))).quantize(decimal.Decimal("0.00"),
                                                                                             decimal.ROUND_HALF_UP)
    return round(price, 2)
def get_limit_down_price(code, pre_price):
    price = (decimal.Decimal(pre_price) * decimal.Decimal(get_limit_down_rate(code))).quantize(decimal.Decimal("0.00"),
                                                                                               decimal.ROUND_HALF_UP)
    return round(price, 2)
def get_thread_id():
@@ -435,5 +450,7 @@
        return f"SZSE.{code}"
    return code
if __name__ == "__main__":
    print(get_buy_max_price(100.123, is_cb=True))
    # print(get_buy_max_price(100.123, is_cb=True))
    print(get_limit_up_price("000333", 56.23))