下载链接:https://academy.qmfquant.com/qimofang.zip
或在官网中根据需求选择不同版本:https://www.qmfquant.com/download
支持电脑配置:windows10 及以上系统,4 核 8G 配置,建议 4 核 16G 以上为佳;服务器建议为 windows 2016 server 4 核 8G 或 16G
账号注册地址:
方式1:https://academy.qmfquant.com/user-sign-2#tab-sign-up
方式2:在客户端界面中也可以完成注册
账号密码找回:在客户端界面,点击登录密码的下方的“找回密码”,通过手机验证码方式,可以将账号密码重置
如果您想使用模拟账户测试,通过下面地址可以一个申请模拟交易账号,申请通过后,客户会收到 simnow 发送的一条短信,短信里面有 6 位数字的账号,然后结合用户在页面注册的密码登录
模拟交易账号注册地址:https://www.simnow.com.cn
右下角期货登录-选择您所在期货账户的期货公司-输入账户密码-登录

1.在下单面板输入正确合约代码
2.持仓面板搜索框选择指定品种

初次使用期魔方平台,新增策略或编辑策略时,会弹出下载编辑器框,需要下载编辑器后才能编写和编译策略,不需要安装python环境,开箱即用,软件已经内置python12.9和pandas、numpy、ta_lib等众多常用库
点击策略-策略列表-新增策略或编辑策略,此时会弹出编译器,可在上面进行策略代码编写

一个完整的策略,一般包含 6 个结构性函数:on_tick,on_init,on_order,on_trade,on_error,on_stop,如果需要收线执行,还需添加 on_bar_run 函数
如果需要输入外置参数,还需添加外置参数配置类:class Params
"""
文件类型: 量化策略
帮助文档: https://qmfquant.com/static/doc/code/strategyEdit.html
期魔方,为您提供专业的量化服务
"""
"""
描述:策略外置参数配置的部分
是否必须编写:可选
编写具体规范见官网“策略编写”文档的策略编写的“外置参数编写”部分
"""
from pydantic import BaseModel, Field
class Params(BaseModel, validate_assignment=True):
"""参数映射模型"""
"""设置外置参数:手数"""
#举例:交易手数的文字文本框的配置代码:volume: int = Field(default=1.0, title="交易手数")
pass
"""
描述:该函数在策略被启动前运行一次;用于配置策略中需要的初始化逻辑;
必要的初始化部分请查询帮助文档
是否必须编写:必选
"""
def on_init(context):
pass
"""
描述:主要的运行逻辑需要编写在 on_tick 函数中;策略成功启动后,每一次报价都会调用一次该函数;
是否必须编写:必选
"""
def on_tick(context):
on_bar_run(on_bar, context) # 如不需要收线执行,则可以不写这行代码
"""
描述:报单回复接口,每次接收到报单时,该函数会被调用,报单信息在 order 对象中;
详细请查询帮助文档;
是否必须编写:可选
"""
def on_order(context, order):
pass
"""
描述:报单回复接口,每次接收到成交单时,该函数会被调用,成交信息在 trade 对象中;
详细请查询帮助文档;
是否必须编写:可选
"""
def on_trade(context, trade):
pass
"""
描述:当挂载账号出现错误操作时,该函数会被调用,错误信息在 err 对象中;
是否必须编写:可选
"""
def on_error(context, err):
pass
"""
描述:当策略触发停止或报错时,调用该函数;可在函数中做一些结算的逻辑;
是否必须编写:可选
"""
def on_stop(context):
pass
说明
获取 K 线的开高低收、时间周期、成交量的序列。
接口案例
def on_tick(context):
klines = get_kline("ru2501","M1",3)
print(f"{klines}")
数据示例
{
'close': [7687.0, 7686.0, 7647.0],
'open': [7687.0, 7687.0, 7686.0],
'high': [7687.0, 7688.0, 7686.0],
'low': [7687.0, 7686.0, 7647.0],
'datetime': [Timestamp('2024-11-15 14:57:00'),
Timestamp('2024-11-15 14:58:00'),
Timestamp('2024-11-15 14:59:00')],
'volume': [0.0, 3.0, 3966.0]
}
以上内容详情请见:获取K线数据
说明
获取指定合约 id 的当前最新报价
接口案例
def on_tick(context):
# 获取合约 ag2412 当前的最新报价
ag2412_tick = get_tick("ag2412")
数据示例
{
"LastPrice": "", # 最新价格
"LowerLimitPrice": 0, # 跌停价格
"UpperLimitPrice": 0 # 涨停价格
# 以下内容已省略
# ...
}
以上内容详情请见:获取tick数据
说明
返回一个 list,用于获取用户目前期货交易账户中所有持仓明细详情的函数。
接口案例
def on_init(context):
# 获取当前持仓的明细
position_info = get_position()
print(f"{position_info}")
数据示例
[
{
'AccountID': 0,
'ActiveTime': '9999',
'CashIn': 0.0,
'CloseAmount': 0,
'CloseProfit': 0
# 以下展示内容已省略
# ...
}
]
以上内容详情请见:获取持仓信息
说明
获取当下已登录期货公司账户信息
接口案例
def on_init(context):
account_info = get_account()
print(f"{account_info}")
数据示例
{
'AccountID': '182958',
'Available': 20833162.898450002, # 可用资金
'Balance': 20940449.198450003, # 账户总资金
'BizType': '',
'BrokerID': '9999',
'CashIn': 0.0,
# 以下展示内容已省略
# ...
}
以上内容详情请见:获取账户信息
说明
建立一个多头仓位,默认采用市价单发送,会返回该订单唯一值
接口案例
def on_tick(context):
res = buy_open(1) # 开单 1 手多单
req_id = res["data"]["result"]["data"]["req_id"] # 通过这个方式可以拿到每次报单的唯一id
数据示例
# 以下是请求成功返回的结果。若请求失败:code 的值为非零 且 msg 会标记请求失败的原因)
{'code': 0, 'data': {...}, 'msg': 'ok'}
说明
建立一个空头仓位,默认采用市价单发送,会返回该订单唯一值
接口案例
def on_tick(context):
res = sell_open(1) # 开单 1 手空单
req_id = res["data"]["result"]["data"]["req_id"] # 通过这个方式可以拿到每次报单的唯一id
数据示例
# 以下是请求成功返回的结果。若请求失败:code 的值为非零 且 msg 会标记请求失败的原因)
{'code': 0, 'data': {...}, 'msg': 'ok'}
说明
结束一个空头仓位,默认采用市价单发送,如果存在今昨仓的持仓,平仓时会先平今,会返回该订单唯一值
接口案例
def on_tick(context):
res = buy_close(1) # 平仓 1 手空单
req_id = res["data"]["result"]["data"]["req_id"] # 通过这个方式可以拿到每次报单的唯一id
数据示例
# 以下是请求成功返回的结果。若请求失败:code 的值为非零 且 msg 会标记请求失败的原因)
{'code': 0, 'data': {...}, 'msg': 'ok'}
说明
结束一个多头仓位,默认采用市价单发送,如果存在今昨仓的持仓,平仓时会先平今,会返回该订单唯一值
接口案例
def on_tick(context):
res = sell_close(1) # 平仓 1 手多单
req_id = res["data"]["result"]["data"]["req_id"] # 通过这个方式可以拿到每次报单的唯一id
数据示例
# 以下是请求成功返回的结果。若请求失败:code 的值为非零且 msg 会标记请求失败的原因)
{'code': 0, 'data': {...}, 'msg': 'ok'}
以上内容详情请见:快捷报单
说明
涉及撤单时调用
接口案例
def on_tick(context):
# 单子具体信息
dict_data = {"Direction": "0",
"OrderPriceType": "2",
# ...
# 单子中 key 必须包含 Symbol 、ExchangeID 、OrderSysID ,否则会存在撤单失败的情况,同 send_order 方法函数的用法举例,订单号 OrderSysID 为共12位右置的字符串,该字符串存在于 on_order 接口返回的订单信息
"OrderSysID": "1863",
"ExchangeID": "SHFE",
"Symbol": "rb2501",
}
# 执行撤单
res = action_order(dict)
print(result)
数据示例
# 以下是请求成功返回的结果。若请求失败:code 的值为非零 且 msg 会标记请求失败的原因)
{'code': 0, 'data': {...}, 'msg': 'ok'}
以上内容详情请见:撤单
策略 -> 策略列表 -> 我的策略 -> 新增策略 -> 填写策略名称,选择语言为 Python(已固定),添加注释说明 -> 确定
如果系统提示下载编写工具,就点击下载安装包,编辑器解压进度条 100% 后,会自动跳转到 VSCode 编辑器页面
以下是双均线策略代码举例: 当 5 日均线上穿 20 日均线时,平空买多; 当 5 日均线下穿 20 日均线时,平多卖空;
"""
文件类型: 量化策略
帮助文档: https://qmfquant.com/static/doc/code/strategyEdit.html
期魔方,为您提供专业的量化服务
"""
"""
描述:导入需要使用的库
是否必须编写:可选
"""
import numpy as np # 导入 numpy 库便于进行数值计算
import talib as ta # 导入 talib 库用于计算均线指标
"""
描述:策略外置参数配置的部分
是否必须编写:可选
编写具体规范见官网“策略编写”文档的策略编写的“外置参数编写”部分
"""
from pydantic import BaseModel, Field
class Params(BaseModel, validate_assignment=True):
"""参数映射模型"""
"""设置外置参数:手数"""
# 举例:交易手数的文字文本框的配置代码:volume:int = Field(default=1, title="交易手数")
pass
"""
描述:该函数在策略被启动前运行一次;用于配置策略中需要的初始化逻辑;
必要的初始化部分请查询帮助文档
是否必须编写:必选
"""
def on_init(context):
context.base_instrument_id = BASE_SETTING.get("Instrument") # 获取运行合约的名称
context.base_period = BASE_SETTING.get("bPeriod") # 获取运行合约的周期
context.position = 0 # 理论持仓量(0 表示不持仓,正数表示多头持仓,负数表示空头持仓)
"""
描述:主要的运行逻辑需要编写在 on_tick 函数中;策略成功启动后,每一次报价都会调用一次该函数;
是否必须编写:必选
"""
def on_tick(context):
# on_bar_run 让 on_bar 函数只在每一个 K 线新产生时运行一次,而不是每一个 tick 都运行一次,这样可以使策略收线运行
on_bar_run(on_bar, context)
"""
描述:每一次新的 K 线数据产生时,调用该函数;
是否必须编写:可选
"""
def on_bar(context):
# 获取当前合约当前周期的 K 线数据(计算 5 周期和 20 周期均线分别需要 5 根和 20 根 K 线数据,所以这里直接取 300 根 K 线数据进行计算)
context.klines = get_kline(context.base_instrument_id, context.base_period, 300)
# 获取 K 线数据中的收盘价数据
context.close_array = context.klines.get("close")
# 计算 5 周期和 20 周期均线,[:-1]是因为计算出来的数据包括了当前未闭合的 K 线数据,所以需要将当前 K 线数据去掉
context.ma5_array = ta.SMA(np.asarray(context.close_array), 5)[:-1] # np.asarray() 将列表转化为数组,方便 talib 库计算
context.ma20_array = ta.SMA(np.asarray(context.close_array), 20)[:-1] # np.asarray() 将列表转化为数组,方便 talib 库计算
volume = 1 # 这里我们每次交易 1 手,也可以在外置参数中设置并在 on_init 函数中获取外置参数中设置的手数
# 计算出来的 5 周期均线和20 周期均线数量不足以判断时,不进行交易
if len(context.ma5_array) < 2 or len(context.ma20_array) < 2:
return
# 发生了死叉情况(即排除最新一根 K 线后,往前数第二根 5 周期均线小于 20 周期均线且往前数第一根 5 周期均线大于20 周期均线),如果当前持有多仓则平多仓
if context.ma5_array[-2] >= context.ma20_array[-2] and context.ma5_array[-1] < context.ma20_array[-1]:
if context.position > 0: # 如果持有多仓
sell_close(volume, context.base_instrument_id) # 平多仓
context.position = 0 # 更新持仓量
# 发生了金叉情况(即排除最新一根 K 线后,往前数第二根 5 周期均线大于20 周期均线且往前数第一根 5 周期均线小于20 周期均线),如果当前持有空仓则平空仓
elif context.ma5_array[-2] <= context.ma20_array[-2] and context.ma5_array[-1] > context.ma20_array[-1]:
if context.position < 0: # 如果持有空仓
buy_close(volume, context.base_instrument_id) # 平空仓
context.position = 0 # 更新持仓量
# 发生了金叉情况,如果当前没有持仓则开多仓
if context.ma5_array[-2] <= context.ma20_array[-2] and context.ma5_array[-1] > context.ma20_array[-1]:
if context.position == 0: # 如果没有持仓
buy_open(volume, context.base_instrument_id) # 开多仓
context.position = volume # 更新持仓量
# 发生了死叉情况,如果当前没有持仓则开空仓
elif context.ma5_array[-2] >= context.ma20_array[-2] and context.ma5_array[-1] < context.ma20_array[-1]:
if context.position == 0: # 如果没有持仓
sell_open(volume, context.base_instrument_id) # 开空仓
context.position = -volume # 更新持仓量
"""
描述:当策略触发停止或报错时,调用该函数;可在函数中做一些结算的逻辑;
是否必须编写:可选
"""
def on_stop(context):
pass
"""
描述:报单回复接口,每次接收到报单时,该函数会被调用,报单信息在 order 对象中;
详细请查询帮助文档;
是否必须编写:可选
"""
def on_order(context,order):
pass
"""
描述:报单回复接口,每次接收到成交单时,该函数会被调用,成交信息在 trade 对象中;
详细请查询帮助文档;
是否必须编写:可选
"""
def on_trade(context,trade):
pass
"""
描述:当挂载账号出现错误操作时,该函数会被调用,错误信息在 err 对象中;
是否必须编写:可选
"""
def on_error(context,err):
pass
编辑好策略文件后,保存文件,在文件中单击右键,选择 Python 编译,编译输出中显示编译成功即可。
【注意】在编辑器中不要运行代码,否则会报错。
说明
推送日志到前端展示的方法
用户可以使用 put_log 函数打印日志,如果没有显示出来,可以将 level 参数提高级别到'ERROR'级别;
接口案例
# 以 INFO 级别示例:
def on_tick(context):
text_data="这是一条日志消息内容"
# 推送日志
put_log(text_data,level="INFO")
print(text_data)
数据示例
"""这是一条日志消息内容"""
以上内容详情请见:推送日志
基于回测的日志信息在软件退出后会写入到用户目录的 AppData\Local\qmfquant\logs\backtest_server 下面
基于任务的日志信息在软件退出后会写入到用户目录的 AppData\Local\qmfquant\logs\task_server 下面
回测-添加-设置基础参数(运行品种、测试模型、开始时间、结束时间这四项必需手动设置)-设置策略参数-点击右下角保存按钮-回测,回测完成后,可点详情,查看策略回测详细报告



任务-选择策略列表-双击策略-选择品种-设置周期-选择账号-设置策略默认参数和外置参数-提交-启动
