第十二章:策略编写初探:API与基本结构

如果说前十一章是对软件操作的指南,相对易于掌握,那么本章将深入到整个系统的核心——策略编写。本章是实现量化交易思想的关键,旨在为开发者提供一个关于”看海量化交易系统”策略框架的直观理解,并详细说明如何基于此框架,一步步构建属于自己的交易策略。我们将重点介绍策略文件的基本结构、核心回调函数,以及与框架交互的关键API。


策略框架是什么

对于每一位交易者而言,心中都有一套独特的交易逻辑。量化交易的本质,便是将这套逻辑转化为代码,让计算机去执行。然而,从零开始编写一套完整的交易程序是复杂且耗时的,需要处理数据获取、订单管理、风险控制、事件驱动等一系列繁琐的底层任务。

策略框架正是为了解决这一问题而生。可以将它理解为一个半成品的交易机器人,它已经为开发者搭建好了坚实的骨架,处理了所有与交易逻辑无关的技术细节。开发者只需要专注于策略本身,将交易思想填充到框架预留的接口中,即可快速构建出功能完备、稳定可靠的自动化交易策略。

为了贴近主流的量化实践和用户习惯,khQuant 定义了一套符合直觉的策略框架。它主要包含四个核心部分,分别对应策略生命周期中的不同阶段:

  • 初始化 (init): 策略开始运行时,用于进行全局设置,仅执行一次。
  • 盘前回调 (khPreMarket): 每个交易日开盘前,用于执行每日的准备工作。
  • 主回调 (khHandlebar): 在盘中根据设定的频率被反复调用,是策略逻辑的核心。
  • 盘后回调 (khPostMarket): 每个交易日收盘后,用于执行当日的复盘和清理任务。

这四个部分均以函数的形式存在于策略文件中。框架会在特定的时间点自动调用这些函数,并将包含当前市场行情、账户资金、持仓情况等所有必要信息的 context 对象作为参数传递给它们。在函数中完成逻辑判断后,只需返回标准的交易指令(我们称之为”信号”),框架便会自动执行后续的下单操作。这种设计极大地简化了策略编写的复杂度,使开发者可以聚焦于策略逻辑本身,而非底层实现。


12.1 策略框架一览

一个策略文件本质上是一个标准的Python脚本,通过实现框架预定义的一系列函数来完成策略逻辑。以下是一个策略文件的最简化结构,它包含了所有主要的回调函数,可以作为开始编写新策略的模板。

from typing import Dict, List

def init(stock_list, context):
    """
    策略初始化函数,在任务开始时仅执行一次。
    用于定义全局变量、加载外部数据等。
    """
    pass

def khHandlebar(context: Dict) -> List[Dict]:
    """
    策略核心逻辑,会被框架根据设定的频率反复调用。
    负责行情判断和生成交易信号。
    """
    signals = []
    return signals

def khPreMarket(context: Dict) -> List[Dict]:
    """
    盘前处理函数(可选)。
    在每日开盘前的指定时间点调用。
    """
    signals = []
    return signals

def khPostMarket(context: Dict) -> List[Dict]:
    """
    盘后处理函数(可选)。
    在每日收盘后的指定时间点调用。
    """
    signals = []
    return signals

12.2 核心回调函数详解

框架通过在特定时机调用策略文件中的特定函数来驱动策略运行。开发者需要根据需求实现这些函数。为了更好地理解,可以参考我们提供的 strategies/MACD.py 策略示例文件,它展示了如何实现一个完整的策略。

12.2.1 init(stock_list, context) – 初始化函数

  • 执行时机:在整个回测或交易任务开始时,被框架调用一次
  • 核心作用:用于执行策略的全局初始化任务,如设置参数、加载数据等。
  • 参数说明
    • stock_list (list): 框架传入的股票池列表,例如 ['000001.SZ', '600000.SH']
    • context (dict): 一个包含初始化时刻上下文信息的字典。其内部详细结构如下:
    • __current_time__ (dict): 包含当前时间信息的字典。
      • timestamp: (int) 标准Unix时间戳。
      • datetime: (str) 格式为 “YYYY-MM-DD HH:MM:SS” 的日期时间字符串。
      • date: (str) 格式为 “YYYY-MM-DD” 的日期字符串。
      • time: (str) 格式为 “HH:MM:SS” 的时间字符串。
    • __account__ (dict): 包含账户资金信息的字典。
      • account_type: (str) 账户类型 (例如, ‘STOCK’)。
      • account_id: (str) 账户ID。
      • cash: (float) 当前可用资金。
      • frozen_cash: (float) 冻结资金。
      • market_value: (float) 持仓市值。
      • total_asset: (float) 总资产。
      • benchmark: (str) 基准指数代码。
    • __positions__ (dict): 包含持仓信息的字典,在初始化时通常为空 {}
    • __framework__ (object): 框架核心类的实例。它包含了最全面的框架信息和功能接口。如果其他上下文参数不包含所需信息,可以尝试通过此对象获取。

12.2.2 khHandlebar(context) – 策略主逻辑函数

  • 执行时机:根据主界面”运行驱动区”设置的触发方式,被框架反复、高频地调用。
  • 核心作用:这是实现交易策略核心逻辑的地方,包括行情判断、信号生成、下单等。
  • 参数说明
    • context (dict): 包含当前时间点所有可用信息的字典,其结构为:
    • __current_time__ (dict): 包含当前时间信息的字典。
      • timestamp: (int) 标准Unix时间戳。
      • datetime: (str) 格式为 “YYYY-MM-DD HH:MM:SS” 的日期时间字符串。
      • date: (str) 格式为 “YYYY-MM-DD” 的日期字符串。
      • time: (str) 格式为 “HH:MM:SS” 的时间字符串。
    • __account__ (dict): 包含账户资金信息的字典。
      • account_type: (str) 账户类型。
      • account_id: (str) 账户ID。
      • cash: (float) 当前可用资金。
      • frozen_cash: (float) 冻结资金。
      • market_value: (float) 持仓市值。
      • total_asset: (float) 总资产。
      • benchmark: (str) 基准指数代码。
    • __positions__ (dict): 包含当前持仓信息的字典。其结构为 {股票代码: 持仓详情}。持仓详情是一个字典,包含了该股票的详细持仓信息,其内部字段如下:
      • account_type: (int) 账户类型。
      • account_id: (str) 账户ID。
      • stock_code: (str) 股票代码。
      • volume: (int) 持仓数量。
      • can_use_volume: (int) 可用数量(可卖出数量)。
      • open_price: (float) 当日开盘价。
      • market_value: (float) 持仓市值。
      • frozen_volume: (int) 冻结数量。
      • on_road_volume: (int) 在途数量。
      • yesterday_volume: (int) 昨日持仓数量。
      • avg_price: (float) 持仓成本价。
      • current_price: (float) 当前市价。
      • direction: (int) 持仓方向。
      • profit: (float) 持仓浮动盈亏。
      • profit_ratio: (float) 持仓盈亏率。
    • __framework__ (object): 框架核心类的实例。它包含了最全面的框架信息和功能接口。如果其他上下文参数不包含所需信息,可以尝试通过此对象获取。
    • [股票代码] (pandas.Series): 以股票代码(如'000001.SZ')为键,值为一个Pandas Series对象,包含了该股票在当前时间点的所有行情字段(如open, high, low, close, volume等)。
  • 返回值:
    • 该函数需要返回一个交易信号列表 (List[Dict])。框架在收到返回的列表后,会自动解析其中的每一条指令,并调用底层的交易接口去执行。如果列表为空,则框架认为当前时间点无任何操作。
    • 一个标准的交易信号字典包含以下键值对:
键 (Key) 类型 (Type) 必填 说明
code str 股票代码,必须是标准的QMT格式,例如 '000001.SZ''600036.SH'
action str 交易动作。可选值为 ‘buy’ (买入) 或 ‘sell’ (卖出)。
price float 交易价格。
volume int 交易数量,必须是100的整数倍。
reason str 交易原因或备注。此信息会显示在日志和交易记录中。
timestamp int 信号生成时的时间戳。
  • 关于信号字典的更详细说明,请参考 12.7 交易信号详解

12.2.3 khPreMarket(context) – 盘前处理函数(可选)

  • 执行时机:在每个交易日的指定盘前时间点(如09:00)被调用一次。该功能需要在主界面”盘前盘后触发设置”中勾选”触发盘前回调”才会生效。
  • 参数 context:其结构与 khHandlebar 函数的 context 完全相同。它包含了当天第一个行情数据点的所有信息,包括账户、持仓、以及股票池内所有股票在该时刻的行情数据。
  • 返回值:与 khHandlebar 类似,返回一个交易信号列表 (List[Dict])。
  • 常见用途
    • 每日选股、计算因子。
    • 重置当日的交易状态或计数器。
    • 提前下达一些集合竞价阶段的预埋单。

12.2.4 khPostMarket(context) – 盘后处理函数(可选)

  • 执行时机:在每个交易日的指定盘后时间点(如15:30)被调用一次。该功能需要在主界面”盘前盘后触发设置”中勾选”触发盘后回调”才会生效。
  • 参数 context:其结构与 khHandlebar 函数的 context 完全相同。它包含了当天最后一个行情数据点的所有信息,包括账户、持仓、以及股票池内所有股票在该时刻的行情数据。
  • 返回值:与 khHandlebar 类似,返回一个交易信号列表 (List[Dict])。
  • 常见用途
    • 当日交易复盘、业绩归因分析。
    • 保存当日的策略状态或数据到本地文件。
    • 清理当日持仓,或为下一个交易日做准备。

12.3 获取时间数据

在策略中,所有时间相关的信息都储存在 context['__current_time__'] 这个字典中。通过访问它,可以获取到策略当前执行点的精确时间。

  • context['__current_time__']['timestamp']: 返回一个整数形式的Unix时间戳。
  • context['__current_time__']['datetime']: 返回 YYYY-MM-DD HH:MM:SS 格式的字符串,最常用。
  • context['__current_time__']['date']: 返回 YYYY-MM-DD 格式的日期字符串。
  • context['__current_time__']['time']: 返回 HH:MM:SS 格式的时间字符串。

示例:实现简单的择时逻辑

def khHandlebar(context: Dict) -> List[Dict]:
    time_info = context['__current_time__']

    # 获取当前时间字符串,如 '09:31:00'
    current_time = time_info['time']

    # 简单的交易时间控制:只在上午10点后、下午2点半前进行交易判断
    if "10:00:00" < current_time < "14:30:00":
        # 在这里编写主要的策略逻辑...
        print("处于交易时间段,执行策略。")
    else:
        # 非交易时间段,不执行任何操作
        print("非交易时间段,跳过。")

    return []

12.4 获取账户数据

账户的资金状况信息储存在 context['__account__'] 字典中,它提供了账户资产的实时快照。

  • context['__account__']['cash']: (float) 当前可用于交易的现金。
  • context['__account__']['market_value']: (float) 所有持仓按当前市价计算的总市值。
  • context['__account__']['total_asset']: (float) 总资产,即 cash + market_value
  • context['__account__']['frozen_cash']: (float) 因挂单而冻结的资金。

示例:根据资金动态计算买入量

def khHandlebar(context: Dict) -> List[Dict]:
    account = context['__account__']

    # 获取当前可用资金
    available_cash = account['cash']

    # 设定一个目标仓位:使用当前可用资金的20%
    cash_to_use = available_cash * 0.2

    # 获取 '000001.SZ' 的当前价格
    stock_data = context.get('000001.SZ')
    if stock_data is not None and not stock_data.empty:
        stock_price = stock_data['close']

        # 计算理论上可以买入多少股,并向下取整到100的倍数
        if stock_price > 0:
            volume_to_buy = int(cash_to_use / stock_price / 100) * 100
            if volume_to_buy > 0:
                print(f"资金充足,计划以 {stock_price} 元的价格买入 {volume_to_buy} 股 000001.SZ")
                # 此处可以构建并返回一个买入信号

    return []

12.5 获取持仓数据

持仓信息 context['__positions__'] 是一个字典,键为股票代码,值为该股票的详细持仓信息字典。这使得检查特定持仓、获取持仓细节变得非常方便。

示例:实现持仓股票的止盈止损

def khHandlebar(context: Dict) -> List[Dict]:
    positions = context['__positions__']
    signals = []

    # 检查是否持有 '600519.SH' (贵州茅台)
    if '600519.SH' in positions:
        # 获取该持仓的详细信息
        pos_info = positions['600519.SH']

        volume = pos_info['volume']
        profit_ratio = pos_info['profit_ratio'] # 获取持仓盈亏率

        print(f"持有 {volume} 股 600519.SH,当前盈利 {profit_ratio*100:.2f}%")

        # 止盈逻辑:如果盈利超过10%,就全部卖出
        if profit_ratio > 0.10:
            sell_signal = {
                'action': 'sell',
                'code': '600519.SH',
                'volume': volume, # 卖出全部持仓
                'remark': '盈利超过10%,止盈'
            }
            signals.append(sell_signal)

        # 止损逻辑:如果亏损超过5%,就全部卖出
        elif profit_ratio < -0.05:
            sell_signal = {
                'action': 'sell',
                'code': '600519.SH',
                'volume': volume, # 卖出全部持仓
                'remark': '亏损超过5%,止损'
            }
            signals.append(sell_signal)

    return signals

12.6 获取当前运行配置

在某些复杂的策略场景中,可能需要在策略逻辑内部获取在GUI界面上配置的参数,例如获取设置的基准合约代码,或者根据不同的手续费配置调整交易行为。

这些配置信息可以通过 context 中的 __framework__ 对象进行访问。

  • context['__framework__'].config: 这是一个 khConfig.KhConfig 类的实例,持有本次运行的所有配置信息。

示例:在策略中获取基准合约和手续费配置

def init(stock_list, context):
    # 从框架对象中获取配置实例
    config = context['__framework__'].config

    # 读取回测配置中的 'benchmark' 参数
    benchmark_code = config.get_config('backtest.benchmark')
    print(f"当前配置的基准合约为: {benchmark_code}")

    # 读取交易成本中的佣金比例
    commission_rate = config.get_config('backtest.trade_cost.commission_rate')
    print(f"当前配置的佣金比例为: {commission_rate}")

12.7 交易信号详解

交易信号是策略与交易执行模块沟通的唯一方式。它是一个包含了所有交易必要信息的Python字典。khHandlebarkhPreMarketkhPostMarket的返回值以及__framework__.trade()的参数都是交易信号。

一个标准的交易信号字典包含以下键值对:

键 (Key) 类型 (Type) 必填 说明
code str 股票代码,必须是标准的QMT格式,例如'000001.SZ''600036.SH'
action str 交易动作。可选值为 ‘buy’ (买入) 或 ‘sell’ (卖出)。
price float 交易价格。
volume int 交易数量,必须是100的整数倍。
reason str 交易原因或备注。此信息会显示在日志和交易记录中。
timestamp int 信号生成时的时间戳。

示例:

# 以10.5元的价格买入100股平安银行
signal_1 = {
    'code': '000001.SZ',
    'action': 'buy',
    'price': 10.5,
    'volume': 100,
    'reason': 'MACD金叉买入'
}

# 以18.5元的价格卖出200股贵州茅台
signal_2 = {
    'code': '600519.SH',
    'action': 'sell',
    'price': 18.50,
    'volume': 200,
    'reason': '达到止盈位卖出'
}

12.8 在策略中使用日志

为了方便调试和监控策略的内部状态,可以在策略代码中直接调用日志输出功能,将信息发送到看海量化交易系统的日志系统(包括界面和文件)。

核心机制:框架已经对Python内置的 logging 模块进行了配置。因此,开发者无需关心日志的底层实现,只需在策略代码中导入 logging 模块,然后直接调用其标准函数即可。

使用方法:

  1. 在策略文件顶部添加 import logging
  2. 在代码中调用 logging.info(), logging.warning(), logging.error() 等函数。

日志级别与界面上显示的颜色直接对应:

  • 普通信息 (INFO): 使用 logging.info("进入长仓条件判断") 输出常规的流程信息或变量状态。这对应界面上的 白色 文本。
  • 调试信息 (DEBUG): 如果需要输出更详细的、仅在调试时关心的变量值或中间计算结果,可以使用 logging.debug(f"当前ATR值: {atr_value}")。这对应界面上的 浅紫色 文本。(注意:默认配置下,DEBUG级别的日志可能不会显示,需在设置中调整)
  • 警告信息 (WARNING): 当策略遇到一些非致命但需要注意的情况时,比如某个数据获取失败但有备用方案,可以使用 logging.warning("无法获取最新行情,使用上一周期数据代替")。这对应界面上的 橙色 文本,比较醒目。
  • 错误信息 (ERROR): 当策略发生严重错误,可能导致后续逻辑无法正常执行时,应使用 logging.error("计算指标时出现除零错误") 。这对应界面上最醒目的 红色 文本,强烈提示需要检查问题。

示例:

import logging
from typing import Dict, List

def khHandlebar(context: Dict) -> List[Dict]:
    # 检查账户现金
    cash = context['__account__']['cash']
    logging.info(f"当前可用资金: {cash}")

    if cash < 10000:
        logging.warning("可用资金不足1万元,跳过本次交易机会。")
        return []

    # ...后续策略逻辑...
    try:
        # 可能会出错的代码
        risky_value = 1 / 0
    except Exception as e:
        logging.error(f"计算风险值时发生严重错误: {e}", exc_info=True) # exc_info=True会记录完整的错误堆栈

    return []

如何输出醒目的内容?

如果希望某条日志信息在界面上特别突出,最直接的方式是使用 logging.warning()logging.error()ERROR 级别(红色)最为醒目,通常用于指示发生了必须处理的问题。WARNING 级别(橙色)也比较突出,适合用于提示潜在风险或需要关注的状态。请根据信息的重要性和紧急程度,审慎选择合适的级别进行输出。


12.9 策略工具箱:khQTTools 模块详解

为了进一步简化策略开发,khQuant 提供了一个名为 khQTTools.py 的工具模块,其中包含了一系列高效实用的辅助函数。这些工具涵盖了时间判断、交易计算、数据获取等多个方面,能够帮助开发者快速实现复杂的逻辑,避免重复造轮子。

要使用这些工具,只需在策略文件的顶部从 khQTTools 模块导入所需的函数即可。

# 在策略文件顶部导入工具函数
from khQTTools import (
    KhQuTools,
    calculate_max_buy_volume,
    generate_signal,
    get_stock_names,
    khHistory
)

12.9.1 时间工具 (KhQuTools)

KhQuTools 是一个封装了常用时间判断功能的类。使用前需要先进行实例化。

# 在init函数或策略的全局部分实例化
tools = KhQuTools()

is_trade_time()

  • 功能:判断当前时间是否处于A股的常规交易时间段内(09:30-11:30, 13:00-15:00)。
  • 返回值bool,是则返回 True,否则返回 False
  • 使用场景:确保交易逻辑只在开盘时段执行。

示例:

def khHandlebar(context: Dict) -> List[Dict]:
    if not tools.is_trade_time():
        return [] # 非交易时间,直接返回

    # ... 在此编写交易时间内的策略逻辑 ...
    logging.info("交易时间内,执行策略。")
    return []

is_trade_day(date_str)

  • 功能:判断指定日期是否为A股的交易日(会剔除周末和法定节假日)。
  • 参数
    • date_str (str, 可选): YYYY-MM-DD 格式的日期字符串。如果留空,则默认判断当天。
  • 返回值bool,是交易日则返回 True,否则返回 False

示例:

# 判断2024年10月1日是否是交易日
is_trading = tools.is_trade_day("2024-10-01") 
print(f"2024-10-01 是交易日吗? {'是' if is_trading else '否'}")

# 判断今天是否是交易日
is_today_trading = tools.is_trade_day()
print(f"今天是交易日吗? {'是' if is_today_trading else '否'}")

get_trade_days_count(start_date, end_date)

  • 功能:计算两个日期之间的A股交易日天数。
  • 参数
    • start_date (str): YYYY-MM-DD 格式的开始日期。
    • end_date (str): YYYY-MM-DD 格式的结束日期。
  • 返回值int,两个日期之间的交易日总数。

示例:

# 计算2024年全年的交易日天数
days = tools.get_trade_days_count("2024-01-01", "2024-12-31")
print(f"2024年共有 {days} 个交易日。")

12.9.2 交易辅助函数

calculate_max_buy_volume(data, stock_code, price, cash_ratio)

  • 功能:一个非常实用的函数,用于根据可用资金和股价,计算出理论上可以买入的最大股票数量(会自动向下取整到100的倍数)。
  • 参数
    • data (dict): 即策略回调函数中的 context 对象。
    • stock_code (str): 计划买入的股票代码。
    • price (float): 计划买入的价格。
    • cash_ratio (float, 可选): 计划使用的资金比例,默认为 1.0 (即全部可用资金)。
  • 返回值int,可以买入的最大股数。

示例:

def khHandlebar(context: Dict) -> List[Dict]:
    # 计划用50%的资金买入平安银行
    stock_to_buy = '000001.SZ'
    current_price = context.get(stock_to_buy)['close'] # 获取当前价

    # 计算最多能买多少股
    max_volume = calculate_max_buy_volume(context, stock_to_buy, current_price, cash_ratio=0.5)

    if max_volume > 0:
        logging.info(f"资金足够,计划以 {current_price} 的价格买入 {max_volume} 股 {stock_to_buy}")
        # ...后续可以生成并返回交易信号

    return []

generate_signal(data, stock_code, price, ratio, action, reason)

  • 功能:高级信号生成函数。对于买入操作,它会自动计算最大可买股数;对于卖出操作,它会自动计算最大可卖股数。极大简化了信号的创建过程。
  • 参数
    • data (dict): 即 context 对象。
    • stock_code (str): 交易的股票代码。
    • price (float): 交易价格。
    • ratio (float): 比例。当 action'buy' 时,这是资金使用比例;当 action'sell' 时,这是持仓卖出比例。
    • action (str): 交易动作,'buy''sell'
    • reason (str, 可选): 交易原因。
  • 返回值List[Dict],一个包含单个交易信号的列表,如果条件不满足(如无钱可买或无仓可卖),则返回空列表。

示例:

def khHandlebar(context: Dict) -> List[Dict]:
    signals = []

    # 假设 is_rsi_low 和 is_rsi_high 是已经计算好的布尔值
    is_rsi_low = True 
    is_rsi_high = True

    # 1. 如果RSI指标小于30,使用30%的资金买入平安银行
    if is_rsi_low and '000001.SZ' in context:
        # 只需指定买入比例,函数会自动计算股数
        buy_signals = generate_signal(context, '000001.SZ', price=context.get('000001.SZ')['close'], ratio=0.3, action='buy', reason='RSI < 30')
        signals.extend(buy_signals)

    # 2. 如果持有茅台,且RSI指标大于70,卖出50%的仓位
    if '600519.SH' in context['__positions__'] and is_rsi_high:
        # 只需指定卖出比例,函数会自动计算股数
        sell_signals = generate_signal(context, '600519.SH', price=context.get('600519.SH')['close'], ratio=0.5, action='sell', reason='RSI > 70')
        signals.extend(sell_signals)

    return signals

12.9.3 数据获取与处理

khHistory(symbol_list, fields, bar_count, fre_step, current_time=None, skip_paused=False, fq='pre', force_download=False)

  • 功能(核心功能) 获取指定证券的历史K线数据,是计算各种技术指标的基础。

  • 入口参数 (Input):

    • symbol_list (list): 证券代码列表。必须是包含标准QMT格式(如'600000.SH')的字符串列表。
    • fields (list): 希望获取的行情字段列表。常用的字段包括 'time', 'open', 'high', 'low', 'close', 'volume' (成交量), 'amount' (成交额)。返回的DataFrame将包含这些列。
    • bar_count (int): 希望获取的K线数量。例如,bar_count=30fre_step='1d' 将获取过去30个交易日的日K线数据。
    • fre_step (str): K线周期。支持 '1m', '5m', '15m', '30m', '60m' 等分钟线周期,以及 '1d' (日线), '1w' (周线), '1mon' (月线)。
    • current_time (str, 可选): 获取历史数据的结束时间点,格式为 'YYYYMMDDHHMMSS'。如果设为 None 或不提供,则数据截止到当前最新时间。这对于回测中模拟特定时间点的情景非常重要。
    • skip_paused (bool, 可选): 是否跳过停牌日。默认为 False。如果设为 True,返回的 bar_count 根K线将不包含该股票的停牌日,K线是连续的。
    • fq (str, 可选): 复权类型。默认为 'pre' (前复权)。可选值为 'back' (后复权) 或 'none' (不复权)。
    • force_download (bool, 可选): 是否强制从远程服务器下载新数据,忽略本地缓存。默认为 False。在进行数据补全或怀疑本地数据有误时,可设为 True
  • 输出参数 (Output):
    • 返回值: 一个Python字典。
    • 字典结构:
      • 键 (Key): 股票代码字符串 (e.g., '000001.SZ')。
      • 值 (Value): 一个pandas.DataFrame对象,或者在获取失败时为None
    • DataFrame结构:
      • 索引 (Index): 默认的整数索引。
      • 列 (Columns): 与输入的 fields 参数完全对应。例如,如果 fields=['time', 'open', 'close'],DataFrame就会有这三列。time列是 datetime 对象,方便进行时间序列分析。

示例:在 init 中预加载数据,在 khHandlebar 中计算5日均线

import pandas as pd
import logging
from khQTTools import khHistory

# 在全局范围定义一个缓存,用于存储计算好的指标
g = {'sma5': {}}

def init(stock_list, context):
    """
    在初始化时,一次性获取所有股票过去30天的日线数据,用于后续计算。
    """
    logging.info("开始获取历史数据用于初始化...")
    history_data = khHistory(
        symbol_list=stock_list,
        fields=['time', 'open', 'close'],
        bar_count=30,
        fre_step='1d'
    )

    for stock in stock_list:
        df = history_data.get(stock)
        if df is not None and not df.empty:
            # 计算5日均线并存入全局缓存
            g['sma5'][stock] = df['close'].rolling(window=5).mean().iloc[-1]
            logging.info(f"{stock} 的初始5日均线值为: {g['sma5'][stock]}")

def khHandlebar(context: Dict) -> List[Dict]:
    signals = []
    # 假设股票池里有 '000001.SZ'
    stock_code = '000001.SZ'
    if stock_code in context:
        current_price = context.get(stock_code)['close']
        sma5_value = g['sma5'].get(stock_code)

        if sma5_value and current_price > sma5_value:
            logging.info(f"{stock_code} 当前价格上穿5日线,产生买入信号。")
            # 此处可构建买入信号

    # 注意:在实盘中,需要每日更新缓存的指标值,可以在khPreMarket中实现
    return signals

get_stock_names(stock_codes, stock_list_file)

  • 功能:根据股票代码列表,查询并返回对应的股票名称。
  • 参数
    • stock_codes (list/str): 一个或多个股票代码。
    • stock_list_file (str): 包含股票代码和名称映射关系的CSV文件路径。通常是 data/stock_list.csv
  • 返回值:一个字典,键为股票代码,值为股票名称。

示例:

# 假设 stock_list.csv 在 data 目录下
stock_list_path = "data/stock_list.csv" 
names_dict = get_stock_names(['000001.SZ', '600519.SH'], stock_list_path)
# 返回: {'000001.SZ': '平安银行', '600519.SH': '贵州茅台'}
print(names_dict)

风险提示

投资有风险,开户需谨慎。本系统仅为投资者提供量化交易相关的数据处理与分析工具,不构成任何投资建议。 请您在审慎思考后作出选择。特别声明:本系统对您与券商之间的交易、合作不承担任何法律责任。 市场有风险,投资需谨慎。

© 2024 看海量化交易系统 版权所有

官网:www.khsci.com/khQuant