easyquant/jq_channel.py
2025-07-03 23:39:31 +08:00

109 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import Any, List
class exchange:
def close_positions(self, context: Any, position: Any):
"""
关闭所有持仓
"""
raise NotImplementedError("This method should be implemented by subclasses")
def buy_security(self, context: Any, target_list: List[str]) -> None:
"""
买入操作:对目标股票执行买入,下单资金均摊分配
"""
raise NotImplementedError("This method should be implemented by subclasses")
def open_position(self, security: str, value: float) -> bool:
"""
开仓操作:尝试买入指定股票
参数:
security: 股票代码
value: 分配给该股票的资金
返回:
若下单成功(部分或全部成交)返回 True否则返回 False
"""
raise NotImplementedError("This method should be implemented by subclasses")
class jq_channel(exchange):
def __init__(self):
pass
def order_target_value_(self, stock: str, value: float) -> Any:
"""
封装 order_target_value 函数进行下单,同时记录中文日志和异常信息
参数:
security: 股票代码
value: 下单目标金额
返回:
下单后生成的订单对象;若失败返回 None
"""
try:
order = order_target_value(stock, value)
return order
except Exception as e:
return None
def close_positions(self, context: Any, position: Any):
"""
平仓操作:尽可能将指定股票仓位全部卖出
参数:
position: 持仓对象
返回:
若下单后订单全部成交返回 True否则返回 False
"""
security = position.security
order = self.order_target_value_(security, 0)
if order is None:
# log.error(f"股票 {security} 下单失败可能是API调用错误")
return False
if order.status == OrderStatus.held and order.filled == order.amount:
# log.info(f"股票 {security} 卖出订单完全成交")
return True
else:
# log.warning(f"股票 {security} 卖出订单部分成交或未成交,状态: {order.status}, 已成交: {order.filled}/{order.amount}")
return False
def buy_security(self, context: Any, target_list: List[str]) -> None:
"""
买入操作:对目标股票执行买入,下单资金均摊分配
参数:
context: 聚宽平台传入的交易上下文对象
target_list: 目标股票代码列表
"""
position_count = len(context.portfolio.positions)
target_num = len(target_list)
if target_num > position_count:
try:
value = context.portfolio.cash / (target_num - position_count)
except ZeroDivisionError as e:
# log.error(f"资金分摊时除零错误: {e}")
return
for stock in target_list:
if context.portfolio.positions[stock].total_amount == 0:
if self.open_position(stock, value):
# log.info(f"已买入股票 {stock},分配资金 {value:.2f}")
# self.not_buy_again.append(stock)
if len(context.portfolio.positions) == target_num:
break
def open_position(self, security: str, value: float) -> bool:
"""
开仓操作:尝试买入指定股票
参数:
security: 股票代码
value: 分配给该股票的资金
返回:
若下单成功(部分或全部成交)返回 True否则返回 False
"""
order = self.order_target_value_(security, value)
if order is not None and order.filled > 0:
return True
return False