diff --git a/core/main_controller.py b/core/main_controller.py index 9d85473..5fa7601 100644 --- a/core/main_controller.py +++ b/core/main_controller.py @@ -1,5 +1,4 @@ # coding:utf-8 -from os import popen import time, sys from peewee import ModelSelect @@ -11,7 +10,7 @@ import sfgrid_constants from core.sfgrid_trade_controller import StockTradeController from core.util import getInstrumentName, getStockPosition from xtquant.xttrader import XtQuantTrader -from xtquant.xttype import StockAccount, XtOrder, XtTrade +from xtquant.xttype import StockAccount, XtAsset, XtOrder, XtPosition, XtTrade from xtquant import xtdata from xtquant.xttrader import XtQuantTraderCallback import datetime @@ -38,7 +37,7 @@ class SFGridController(XtQuantTraderCallback): subscribe_result = self.xt_trader.subscribe(self.account) print(f'- 交易状态订阅{'成功' if subscribe_result == 0 else '失败'}') self.stock_trade_ctrl = {} - self.init_instrument_pool() + self.init_instrument_pool(self.xt_trader, self.account) self.seq = None print('- 三疯交易系统初始化完成') @@ -95,10 +94,14 @@ class SFGridController(XtQuantTraderCallback): self.refresh_targets() - def init_instrument_pool(self): + def init_instrument_pool(self, xtTrader:XtQuantTrader, account:StockAccount): self.refresh_targets() - for tradeTarget in self.instrument_pool: + for temp in self.instrument_pool: + tradeTarget:strategy_db.TradeTarget = temp + tradeTarget.current_position = getStockPosition(tradeTarget.stock_code, xtTrader, account) + result = tradeTarget.save() + print(f' |- 同步当前持仓信息 {tradeTarget.stock_code}, {tradeTarget.current_position}, result = {result}') stockTradeController = StockTradeController(tradeTarget, self.xt_trader, self.account, tradeTarget.enabled) self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController @@ -121,24 +124,26 @@ class SFGridController(XtQuantTraderCallback): positions = self.xt_trader.query_stock_positions(self.account) if positions: print("\n- 持仓信息") - for pos in positions: + for temp in positions: + pos : XtPosition = temp if pos.m_nVolume <=0: continue print(f"股票代码: {pos.stock_code}-{getInstrumentName(pos.stock_code)}") - print(f"总持仓: {pos.m_nVolume}") - print(f"可用持仓: {pos.m_nCanUseVolume}") + print(f"总持仓: {pos.volume}") + print(f"可用持仓: {pos.can_use_volume}") print(f"持仓成本: {pos.avg_price}") print("---") else: print("\n当前无持仓") def print_account_info(self): - account_info = self.xt_trader.query_stock_asset(self.account) + temp = self.xt_trader.query_stock_asset(self.account) + asset: XtAsset =temp - print(f"\n=== 账户信息 {self.account.account_id} ===") - print(f"可用资金: {account_info.m_dCash}") - print(f"总资产: {account_info.m_dTotalAsset}") - print(f"证券市值: {account_info.m_dMarketValue}") + print(f"=== 账户信息 {self.account.account_id} ===") + print(f"可用资金: {asset.cash}") + print(f"总资产: {asset.total_asset}") + print(f"证券市值: {asset.market_value}") def print_stock_orders(self): orders = self.xt_trader.query_stock_orders(self.account, cancelable_only=True) diff --git a/core/sfgrid_trade_controller.py b/core/sfgrid_trade_controller.py index 4e51805..8d3f308 100644 --- a/core/sfgrid_trade_controller.py +++ b/core/sfgrid_trade_controller.py @@ -1,9 +1,10 @@ from core.strategy_db import TradeTarget -from core.util import getStockPosition, queryPendingOrder +from core.util import getStockPosition, is_trading_time, queryPendingOrder from xtquant import xttrader, xtconstant from xtquant.xttype import StockAccount, XtOrder, XtTrade import sfgrid_constants +import datetime class StockTradeController: @@ -29,7 +30,7 @@ class StockTradeController: self.xt_trader.cancel_order_stock(self.account, order.order_id) if enabled: - print(f" |- 标的交易启动 {self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}") + print(f" |- 标的交易启动 {self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}, position {self.tradeTarget.current_position}") # 建仓状态检查 if self.tradeTarget.current_position == 0 and self.tradeTarget.status == 0: print(f" |- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 建初始仓 买单准备中...") @@ -39,15 +40,13 @@ class StockTradeController: print(f" |- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 建初始仓 买单已发出 InitBuyOrderId: {self.initBuyOrderId} Price: {sfgrid_constants.grid_price[self.tradeTarget.grid_index]} Volume: {sfgrid_constants.grid_volume}") else: # 交易阶段,检查仓位,检查现有订单 - print(f" |- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 已有仓位或非初始状态 无需建初始仓 当前仓位: {getStockPosition(self.tradeTarget.stock_code, self.xt_trader, self.account)} 状态: {self.tradeTarget.status}") - currentPosition = getStockPosition(self.tradeTarget.stock_code, self.xt_trader, self.account) - if sfgrid_constants.grid_volume * TradeTarget.current_position >= currentPosition: - print(f' |- 仓位检查: 持仓需求充足, (gridVolume*gridIndex)={sfgrid_constants.grid_volume * self.tradeTarget.current_position}, 当前持仓:{currentPosition}') + print(f" |- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 已有仓位或非初始状态 无需建初始仓 当前仓位: {self.tradeTarget.current_position} 状态: {self.tradeTarget.status}") + if sfgrid_constants.grid_volume * self.tradeTarget.grid_index <= self.tradeTarget.current_position: + print(f' |- 仓位检查: 持仓需求充足, (gridVolume*gridIndex)={sfgrid_constants.grid_volume * self.tradeTarget.grid_index}, 当前持仓:{self.tradeTarget.current_position}') else: - print(f' |- 仓位检查: 持仓需求不足, (gridVolume*gridIndex)={sfgrid_constants.grid_volume * self.tradeTarget.current_position}, 当前持仓:{currentPosition}') - - self.two_way_order(True, True) - + print(f' |- 仓位检查: 持仓需求不足, (gridVolume*gridIndex)={sfgrid_constants.grid_volume * self.tradeTarget.grid_index}, 当前持仓:{self.tradeTarget.current_position}') + if is_trading_time(): + self.two_way_order(True, True) def isEnabled(self) -> bool: @@ -64,7 +63,7 @@ class StockTradeController: indicator = False if self.tradeTarget.status == 0 and trade.order_id == self.initBuyOrderId : # 此时为建仓成交 - self.tradeTarget.current_position += sfgrid_constants.grid_volume # 当前持仓数,账户原有持仓不在策略范围内 + self.tradeTarget.current_position += trade.traded_volume # 当前持仓数,账户原有持仓不在策略范围内 self.tradeTarget.last_trade_price = trade.traded_price self.tradeTarget.grid_index = 1 self.tradeTarget.status = 1 @@ -76,7 +75,7 @@ class StockTradeController: indicator = True # 双向下单 elif trade.order_id == self.tradeTarget.current_sell_order_no and self.tradeTarget.status == 1: # 上涨一格:此时空单成交 - self.tradeTarget.current_position = -sfgrid_constants.grid_volume + self.tradeTarget.current_position -= trade.traded_volume self.tradeTarget.last_trade_price = trade.traded_price self.tradeTarget.grid_index -= 1 self.tradeTarget.save() @@ -89,11 +88,11 @@ class StockTradeController: indicator = True # 双向下单 elif trade.order_id == self.tradeTarget.current_buy_order_no and self.tradeTarget.status == 1: # 下跌一格:此时多单成交 - self.tradeTarget.current_position = +sfgrid_constants.grid_volume + self.tradeTarget.current_position += trade.traded_volume self.tradeTarget.last_trade_price = trade.traded_price self.tradeTarget.grid_index += 1 self.tradeTarget.save() - print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 下跌 买单已成交 订单ID: {self.tradeTarget.current_buy_order_no} Price: {sfgrid_constants.grid_price[self.tradeTarget.grid_index]} Volume: {sfgrid_constants.grid_volume} 手续费: {trade.commission}") + print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 下跌 买单已成交 订单ID: {self.tradeTarget.current_buy_order_no} Price: {trade.traded_price} Volume: {sfgrid_constants.grid_volume} 手续费: {trade.commission}") print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}') print(f' 当前持仓: {getStockPosition(self.tradeTarget.stock_code, self.xt_trader, self.account)}') print(f' 网格坐标: {self.tradeTarget.grid_index}') @@ -104,7 +103,8 @@ class StockTradeController: # 打印订单信息和订单状态 print(f'|- 非策略内部订单,或订单状态不满足监控条件 {trade.order_id} {trade.stock_code}-{trade.instrument_name} {trade.commission}') - if indicator and self.isEnabled(): + if indicator and self.isEnabled() and is_trading_time(): + print(f'goto two way order') self.two_way_order(True, True) # 双向下单 @@ -123,8 +123,7 @@ class StockTradeController: # Description: 网格跳格,双向下单 def two_way_order(self, buy, sell): - # print(f'current grid index = {self.tradeTarget.grid_index}, grid count = {len(sfgrid_constants.grid_price)}') - + if buy and self.tradeTarget.grid_index+1 < len(sfgrid_constants.grid_price): # 价格没有超过网格下边界,可以下多单 currentPrice = sfgrid_constants.grid_price[self.tradeTarget.grid_index] buyPrice = sfgrid_constants.grid_price[self.tradeTarget.grid_index+1] @@ -134,8 +133,10 @@ class StockTradeController: xtconstant.STOCK_BUY, sfgrid_constants.grid_volume, xtconstant.FIX_PRICE, - buyPrice, - self.getName(), f'{self.tradeTarget.stock_code}_grid_down_{self.tradeTarget.grid_index}_{currentPrice}_{buyPrice}') + buyPrice, + self.getName(), # strategy_name + f'{self.tradeTarget.stock_code}_grid_down_{self.tradeTarget.grid_index}_{currentPrice}_{buyPrice}' # remark + ) self.tradeTarget.current_buy_price = buyPrice print(f' |- 下网格多单 OrderId {self.tradeTarget.current_buy_order_no}, 网格基准价 {currentPrice}, 下单价 {buyPrice}, 下单量 {sfgrid_constants.grid_volume}') @@ -151,5 +152,5 @@ class StockTradeController: sellPrice, self.getName(), f'{self.tradeTarget.stock_code}_grid_up_{self.tradeTarget.grid_index}_{currentPrice}_{sellPrice}') self.tradeTarget.current_sell_price = sellPrice - print(f' |- 下网格多单 OrderId {self.tradeTarget.current_sell_order_no}, 网格基准价 {currentPrice}, 下单价 {sellPrice}, 下单量 {sfgrid_constants.grid_volume}') + print(f' |- 下网格空单 OrderId {self.tradeTarget.current_sell_order_no}, 网格基准价 {currentPrice}, 下单价 {sellPrice}, 下单量 {sfgrid_constants.grid_volume}') self.tradeTarget.save() \ No newline at end of file diff --git a/core/util.py b/core/util.py index f5c57a9..0f576aa 100644 --- a/core/util.py +++ b/core/util.py @@ -1,7 +1,41 @@ import sfgrid_constants import xtquant.xtconstant as xtconstant from xtquant import xtdata, xttrader -from xtquant.xttype import StockAccount, XtOrder +from xtquant.xttype import StockAccount, XtPosition + +import datetime +def is_trading_time(): + """ + 判断当前时间是否在周一至周五的9:30~11:30或13:00~15:00时间段内 + 返回: True(在交易时间内) 或 False(不在交易时间内) + """ + # 获取当前时间 + now = datetime.datetime.now() + + # 获取星期几 (0=周一, 1=周二, ..., 4=周五) + weekday = now.weekday() + + # 判断是否为周一到周五 (0-4) + if weekday < 5: + current_time = now.time() + + # 第一个时间段: 9:30~11:30 + morning_start = datetime.time(9, 30) + morning_end = datetime.time(11, 30) + + # 第二个时间段: 13:00~15:00 + afternoon_start = datetime.time(13, 0) + afternoon_end = datetime.time(15, 0) + + # 判断是否在第一个时间段内 + if morning_start <= current_time <= morning_end: + return True + + # 判断是否在第二个时间段内 + if afternoon_start <= current_time <= afternoon_end: + return True + + return False def getInstrumentName(stock_code): # print(f"getInstrumentName: 获取标的名称 {stock_code}") @@ -13,10 +47,12 @@ def getStockPosition(stock_code: str, xt_trader: xttrader.XtQuantTrader, account volume = 0 positions = xt_trader.query_stock_positions(account) if positions: - for pos in positions: + for temp in positions: + pos:XtPosition = temp if pos.stock_code == stock_code: - volume = pos.m_nVolume + volume = pos.volume break + return volume def minPosition(gridIndex:int): diff --git a/sfgrid_constants.py b/sfgrid_constants.py index 42960ff..f781c07 100644 --- a/sfgrid_constants.py +++ b/sfgrid_constants.py @@ -1,8 +1,20 @@ -miniQMTPath = r'D:\\Programs\\DTQMT_MN\\userdata_mini' # miniQMT软件的安装路径 -# D:\Programs\DTQMT_MN\userdata_mini +# miniQMTPath = r'D:\\Programs\\DTQMT_MN\\userdata_mini' # miniQMT软件的安装路径 +miniQMTPath = r'D:\\Programs\\DTQMT\\userdata_mini' # grid_price = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] # 网格价格设置,从高到低 -grid_price = [10.05, 10.00, 9.95, 9.90, 9.85, 9.80, 9.75, 9.70, 9.65, 9.60, 9.55] # 网格价格设置,从高到低 -grid_volume = 100 # 每个网格的交易手数 -# account_no = '99082560' -account_no = '89009170' # 交易账号 +grid_price = [ + 1.665, + 1.660, + 1.655, + 1.650, + 1.645, + 1.640, + 1.635, + 1.630, + 1.625, + 1.620, + 1.615 + ] # 网格价格设置,从高到低 +grid_volume = 200 # 每个网格的交易手数 +account_no = '99082560' +# account_no = '89009170' # 交易账号 max_enabled_targets = 10 \ No newline at end of file diff --git a/starter.py b/starter.py index 4273292..3736232 100644 --- a/starter.py +++ b/starter.py @@ -1,11 +1,10 @@ # coding:utf-8 import sys -import chardet - -# from ui.ui import InitUI, Loop sys.stdout.reconfigure(encoding='utf-8') # 设置标准输出编码为UTF-8 from core.main_controller import ctrl import core.util as util +import sfgrid_constants as sdConstants +from xtquant import xtdata def interact(): """执行后进入repl模式""" @@ -42,14 +41,6 @@ def pauseTrade(index:int): def stockTradeCtrl(index: int): return ctrl.stock_trade_ctrl[ctrl.instrument_pool[index].stock_code] -def importCsv(path:str): - with open(path, 'r', encoding='utf-8', errors='replace') as infile: - result = chardet.detect(infile) - print(result['encoding']) - # reader = csv.reader(infile) - # data = [row for row in reader] - # print(data) - def help(): print("基础指令:") @@ -63,7 +54,6 @@ def help(): print(" positionInfo() - 打印持仓信息\n") print(" startTrade(index) - 启动标的交易") print(" pauseTrade(index) - 暂停标的交易") - print(" importCsv(path) - 导入CSV文件") print(" ===================================================") print("内部指令:") print(" stockTradeCtrl(index) - 获取标的交易控制器")