|
|
@@ -657,11 +657,21 @@ def check_open_and_stop(context):
|
|
|
continue
|
|
|
# 执行开仓
|
|
|
log.info(f" 准备开仓: {symbol} {direction}")
|
|
|
- target_hands, single_hand_margin = calculate_target_hands(context, dominant_future, direction)
|
|
|
+ target_hands, single_hand_margin, single_hand_exceeds_limit = calculate_target_hands(
|
|
|
+ context, dominant_future, direction)
|
|
|
|
|
|
if target_hands > 0:
|
|
|
- success = open_position(context, dominant_future, target_hands, direction, single_hand_margin,
|
|
|
- f'均线形态开仓', crossed_ma_details=score_details, entry_snapshot=entry_snapshot)
|
|
|
+ success = open_position(
|
|
|
+ context,
|
|
|
+ dominant_future,
|
|
|
+ target_hands,
|
|
|
+ direction,
|
|
|
+ single_hand_margin,
|
|
|
+ single_hand_exceeds_limit,
|
|
|
+ f'均线形态开仓',
|
|
|
+ crossed_ma_details=score_details,
|
|
|
+ entry_snapshot=entry_snapshot
|
|
|
+ )
|
|
|
if success:
|
|
|
log.info(f" ✓✓ {symbol} 开仓成功,从候选列表移除")
|
|
|
candidates_to_remove.append(dominant_future)
|
|
|
@@ -1170,15 +1180,27 @@ def check_historical_ma_pattern_consistency(historical_data, direction, lookback
|
|
|
|
|
|
############################ 交易执行函数 ###################################
|
|
|
|
|
|
-def open_position(context, security, target_hands, direction, single_hand_margin, reason='',
|
|
|
+def open_position(context, security, target_hands, direction, single_hand_margin,
|
|
|
+ single_hand_exceeds_limit, reason='',
|
|
|
crossed_ma_details=None, entry_snapshot=None):
|
|
|
- """开仓并可选地在成交后校验保证金"""
|
|
|
+ """开仓并可选地在成交后校验保证金
|
|
|
+
|
|
|
+ Args:
|
|
|
+ single_hand_exceeds_limit: bool,当单手保证金超过最大限制时为True
|
|
|
+ """
|
|
|
try:
|
|
|
# 记录交易前的可用资金
|
|
|
cash_before = context.portfolio.available_cash
|
|
|
|
|
|
- # 使用order_target按手数开仓
|
|
|
- order = order_target(security, target_hands, side=direction)
|
|
|
+ # 根据单手保证金情况选择下单方式
|
|
|
+ use_value_order = (not single_hand_exceeds_limit) and getattr(g, 'max_margin_per_position', 0) > 0
|
|
|
+ if use_value_order:
|
|
|
+ target_value = g.max_margin_per_position
|
|
|
+ order = order_target_value(security, target_value, side=direction)
|
|
|
+ log.debug(f"使用order_target_value下单: {security} {direction} 目标价值 {target_value}")
|
|
|
+ else:
|
|
|
+ order = order_target(security, target_hands, side=direction)
|
|
|
+ log.debug(f"使用order_target按手数下单: {security} {direction} 目标手数 {target_hands}")
|
|
|
log.debug(f"order: {order}")
|
|
|
|
|
|
# 检查订单状态,如果为'new'说明当晚没有夜盘
|
|
|
@@ -1266,8 +1288,8 @@ def open_position(context, security, target_hands, direction, single_hand_margin
|
|
|
f"保证金: {margin_change:.0f}, 资金变化: {cash_change:.0f}, 原因: {reason}, "
|
|
|
f"穿越均线: {crossed_ma_str}")
|
|
|
|
|
|
- log.debug(f"开仓后检查并补足保证金占用,使其满足最小要求")
|
|
|
- verify_position_margin_requirement(context, security)
|
|
|
+ # log.debug(f"开仓后检查并补足保证金占用,使其满足最小要求")
|
|
|
+ # verify_position_margin_requirement(context, security)
|
|
|
|
|
|
return True
|
|
|
|
|
|
@@ -1508,7 +1530,11 @@ def has_reached_trading_start(current_dt, trading_start_time_str, has_night_sess
|
|
|
return True
|
|
|
|
|
|
def calculate_target_hands(context, security, direction):
|
|
|
- """计算目标开仓手数"""
|
|
|
+ """计算目标开仓手数
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ tuple: (target_hands, single_hand_margin, single_hand_exceeds_limit)
|
|
|
+ """
|
|
|
current_price = get_current_data()[security].last_price
|
|
|
underlying_symbol = security.split('.')[0][:-4]
|
|
|
|
|
|
@@ -1525,8 +1551,9 @@ def calculate_target_hands(context, security, direction):
|
|
|
|
|
|
# 根据单个标的最大持仓保证金限制计算开仓数量
|
|
|
max_margin = g.max_margin_per_position
|
|
|
+ single_hand_exceeds_limit = single_hand_margin > max_margin
|
|
|
|
|
|
- if single_hand_margin <= max_margin:
|
|
|
+ if not single_hand_exceeds_limit:
|
|
|
# 如果单手保证金不超过最大限制,计算最大可开仓手数
|
|
|
max_hands = int(max_margin / single_hand_margin)
|
|
|
max_hands_by_cash = int(available_cash / single_hand_margin)
|
|
|
@@ -1539,14 +1566,14 @@ def calculate_target_hands(context, security, direction):
|
|
|
|
|
|
log.info(f"单手保证金: {single_hand_margin:.0f}, 目标开仓手数: {actual_hands}")
|
|
|
|
|
|
- return actual_hands, single_hand_margin
|
|
|
+ return actual_hands, single_hand_margin, single_hand_exceeds_limit
|
|
|
else:
|
|
|
# 如果单手保证金超过最大限制,默认开仓1手
|
|
|
actual_hands = 1
|
|
|
|
|
|
log.info(f"单手保证金: {single_hand_margin:.0f} 超过最大限制: {max_margin}, 默认开仓1手")
|
|
|
|
|
|
- return actual_hands, single_hand_margin
|
|
|
+ return actual_hands, single_hand_margin, single_hand_exceeds_limit
|
|
|
|
|
|
def check_symbol_prefix_match(symbol, context, hold_symbols):
|
|
|
"""检查是否有相似的持仓品种"""
|