🚀 AI 一键生成 joinquant 策略代码

JoinQuant 融资融券策略:如何使用 get_margincash_stocks 动态筛选可融资标的?

joinquant | 发布时间: 2025/12/16
以下内容由 EasyQuant 生成。

问题描述

如何只在当前可以融资融券的股票里进行交易?

解决方案

在聚宽(JoinQuant)平台中,若要限制策略只在当前可融资(融资买入)或可融券(融券卖出)的标的中进行交易,主要使用以下两个API函数:

  1. get_margincash_stocks(): 获取当前可融资(做多)的股票列表。
  2. get_marginsec_stocks(): 获取当前可融券(做空)的股票列表。

通常情况下,我们会在 before_trading_start 函数中调用这些接口,获取当天的两融标的列表,并将其与我们选定的股票池(如沪深300)取交集,从而过滤掉不可融资融券的股票。

以下是一个完整的策略示例。该策略选取沪深300成分股,并过滤出其中既可以融资也可以融券的股票作为最终交易股票池,然后随机买入其中5只。

# -*- coding: utf-8 -*-
import jqdata
import random

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    
    # 定义全局变量,用于存储每日筛选后的股票池
    g.target_stocks = []

    # 每天开盘前运行
    run_daily(before_market_open, time='09:00')
    # 每天开盘时运行
    run_daily(market_open, time='09:30')

def before_market_open(context):
    """
    开盘前筛选股票
    """
    # 1. 获取基础股票池(例如:沪深300成分股)
    base_pool = get_index_stocks('000300.XSHG')
    
    # 2. 获取当前可融资(买入)的标的列表
    margin_cash_stocks = get_margincash_stocks()
    
    # 3. 获取当前可融券(卖出)的标的列表
    # 如果你的策略只需要融资买入,可以只用上面的 margin_cash_stocks
    # 如果你的策略涉及融券做空,建议同时检查 margin_sec_stocks
    margin_sec_stocks = get_marginsec_stocks()
    
    # 4. 筛选:取交集
    # 逻辑:在沪深300中,且同时在融资列表和融券列表中的股票
    # 注意:set操作可以提高查找效率
    valid_stocks = set(base_pool) & set(margin_cash_stocks) & set(margin_sec_stocks)
    
    g.target_stocks = list(valid_stocks)
    
    log.info("今日符合条件的融资融券标的数量: %d" % len(g.target_stocks))

def market_open(context):
    """
    开盘交易逻辑
    """
    # 如果没有符合条件的股票,直接返回
    if len(g.target_stocks) == 0:
        return

    # 卖出不在今日目标池中的持仓
    for security in context.portfolio.positions:
        if security not in g.target_stocks:
            order_target(security, 0)
            log.info("卖出不再是两融标的的股票: %s" % security)

    # 简单的买入逻辑示例:随机买入目标池中的5只股票
    # 实际策略中请替换为你的选股因子逻辑
    buy_count = 5
    
    # 资金分配
    cash_per_stock = context.portfolio.available_cash / buy_count
    
    # 随机选择
    stocks_to_buy = random.sample(g.target_stocks, min(len(g.target_stocks), buy_count))
    
    for stock in stocks_to_buy:
        order_value(stock, cash_per_stock)
        log.info("买入两融标的: %s" % stock)

代码逻辑解析

  1. 获取数据

    • 使用 get_margincash_stocks() 获取交易所披露的最新可融资标的。
    • 使用 get_marginsec_stocks() 获取交易所披露的最新可融券标的。
    • 这两个函数在回测模式下会自动获取回测当天的历史数据,在实盘/模拟交易中会获取最新数据,避免了未来函数。
  2. 集合运算

    • 代码中使用 set(list_a) & set(list_b) 的方式取交集。这确保了选出的股票既属于你的基础股票池(如沪深300),又是交易所规定的两融标的。
  3. 时机选择

    • 筛选逻辑放在 before_market_open (09:00) 中执行。这是因为两融标的名单通常在交易日开始前就已经确定,提前筛选可以提高盘中交易的效率。

常见问题 (Q&A)

Q: get_margincash_stocksget_marginsec_stocks 有什么区别?
A: get_margincash_stocks 返回的是可以融资买入(借钱买股)的股票列表;get_marginsec_stocks 返回的是可以融券卖出(借股卖出)的股票列表。虽然大部分标的两者皆可,但仍有部分股票只允许融资不允许融券,或者相反。

Q: 为什么回测时获取不到当天的两融数据?
A: 交易所的数据通常在收盘后更新。在回测中,如果查询当天的两融列表,系统通常返回的是截止到前一个交易日的数据(或者当天盘前已知的数据),这是为了防止未来函数。在聚宽中,直接调用这两个函数即可获取策略当前时间点可用的最新名单。

Q: 如果我想开通融资融券账户进行杠杆交易,代码需要修改吗?
A: 需要。上面的代码仅限制了标的范围,但使用的是普通账户(自有资金)。如果要进行杠杆交易(融资买入或融券卖出),需要在 initialize 中使用 set_subportfolios 将账户类型设置为 'stock_margin',并使用 margincash_open (融资买入) 或 marginsec_open (融券卖出) 等专用接口下单。

Q: 如何判断单只股票是否可融资?
A: 可以直接判断股票代码是否在列表中,例如:

if '000001.XSHE' in get_margincash_stocks():
    print("平安银行可融资")