FMZ 发布 python 本地 回测引擎

Author: 小小梦, Created: 2018-04-13 09:48:31, Updated: 2019-08-19 16:30:05

FMZ 发布 python 本地 回测引擎

FMZ backtest engine python package FMZ 回测引擎 python 库 support python2 and python3, support Windows, Linux, Mac 支持 python2 和 python3 , 支持 windows 系统,Linux 系统 ,苹果Mac OS 系统

install

安装 在命令行 输入以下命令:

pip install https://github.com/fmzquant/backtest_python/archive/master.zip
  • 注意: 苹果 Mac 系统 安装时,如果有安全限制,需要 在 pip 命令前加 sudo 命令,整条安装命令执行前会 要求输入 系统密码。

simple example

简单例子

'''backtest
start: 2018-02-19 00:00:00
end: 2018-03-22 12:00:00
period: 15m
exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}]
'''
from fmz import *
task = VCtx(__doc__) # initialize backtest engine from __doc__
print exchange.GetAccount()
print exchange.GetTicker()
print task.Join() # print backtest result

The config string can be generated automatically by saving the backtest configuration in the strategy edit page. 配置字符串可以通过策略编辑界面里的保存回测配置来自动生成

meta

documentation

API 文档:(即范例中 调用 GetAccount 等函数的文档)

Python 代码简单注释:

'''backtest
start: 2018-02-19 00:00:00
end: 2018-03-22 12:00:00
period: 15m
exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}]
'''
from fmz import *                                                  # 引用 发明者量化 库
task = VCtx(__doc__) # initialize backtest engine from __doc__     # 调用 VCtx 函数 根据 __doc__初始化。
print exchange.GetAccount()                                        # 测试 GetAccount 函数,并打印 回测系统测试交易所账户信息
print exchange.GetTicker()                                         # 测试 GetTicker 函数,并打印 回测系统 行情信息
print task.Join() # print backtest result                          # 调用 初始化后的 task 对象 显示回测结果
  • __doc__

    是两个下划线。__doc__用来访问模块,类声明或者函数的声明中第一个未被赋值的字符串,
    可以是被""" ""","" "",' ',括起来的,作用就是把 代码中 '''backtest   ...  ''' 的回测配置信息  传入 VCtx 类构造函数构造对象。
    
  • 修改下 测试代码, 看看 具体 Log 、GetTicker 函数如何调用。

    # coding=UTF-8
    
    '''backtest
    start: 2018-02-19 00:00:00
    end: 2018-03-22 12:00:00
    period: 15m
    exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}]
    '''
    
    from fmz import *                                                # 引用 发明者量化 库
    task = VCtx(__doc__) # initialize backtest engine from __doc__     # 调用 VCtx 函数 根据 __doc__初始化。
    print exchange.GetAccount()                                        # 测试 GetAccount 函数,并打印 回测系统测试交易所账户信息
    Log("\n 调用Log")
    Log("调用 exchange.GetTicker() : ", exchange.GetTicker())
    print task.Join() # print backtest result                          # 调用 初始化后的 task 对象 显示回测结果
    
    • print exchange.GetAccount() 代码输出显示的内容为:
    {'Balance': 3.0, 'Stocks': 0.0, 'FrozenBalance': 0.0, 'FrozenStocks': 0.0}
    
    • Log("\n 调用Log") 、 Log("调用 exchange.GetTicker() : ", exchange.GetTicker())

    输出的内容在 print task.Join() 输出数据 结构内:

    {
        "Chart": {
     	   "Cfg": "",
     	   "Datas": []
        },
        "Elapsed": 42000000,
        "Finished": true,
        "Indicators": {},
        "LoadBytes": 441845,
        "LoadElapsed": 24000000,
        "LogsCount": 2,
        "Profit": 0.0,
        "ProfitLogs": [],
        "Progress": 100.0,
        "RuntimeLogs": [                                                  # 调用输出内容在此处
     	   [1, 1518969600200, 5, "", 0, 0.0, 0.0, "\n 调用Log", "", ""],
     	   [2, 1518969600400, 5, "", 0, 0.0, 0.0, "调用 exchange.GetTicker() :  {'Sell': 0.02113476, 'Volume': 519.6953, 'Buy': 0.02113474, 'Last': 0.02113475, 'High': 0.02113476, 'Time': 1518969600000L, 'Low': 0.02113474}", "", ""]
        ],
        "Snapshort": [{
     	   "Balance": 3.0,
     	   "BaseCurrency": "LTC",
     	   "Commission": 0.0,
     	   "FrozenBalance": 0.0,
     	   "FrozenStocks": 0.0,
     	   "Id": "OKEX",
     	   "QuoteCurrency": "BTC",
     	   "Stocks": 0.0,
     	   "Symbols": {
     		   "LTC_BTC_OKEX": {
     			   "Last": 0.01893785
     		   }
     	   },
     	   "TradeStatus": {}
        }],
        "Status": "",
        "Task": {
     	   "Args": null,
     	   "Exchanges": [{
     		   "Balance": 3,
     		   "BaseCurrency": "LTC",
     		   "BasePeriod": 300000,
     		   "BasePrecision": 4,
     		   "DepthDeep": 5,
     		   "FaultTolerant": 0,
     		   "FeeDenominator": 5,
     		   "FeeMaker": 75,
     		   "FeeMin": 0,
     		   "FeeTaker": 80,
     		   "Id": "OKEX",
     		   "Label": "OKEX",
     		   "PriceTick": 1e-08,
     		   "QuoteCurrency": "BTC",
     		   "QuotePrecision": 8,
     		   "SlipPoint": 0,
     		   "Stocks": 0
     	   }],
     	   "Options": {
     		   "DataServer": "q.botvs.net",
     		   "MaxChartLogs": 800,
     		   "MaxProfitLogs": 800,
     		   "MaxRuntimeLogs": 800,
     		   "NetDelay": 200,
     		   "Period": 900000,
     		   "RetFlags": 189,
     		   "SnapshortPeriod": 300000,
     		   "TimeBegin": 1518969600,
     		   "TimeEnd": 1521691200,
     		   "UpdatePeriod": 5000
     	   }
        },
        "TaskStatus": 1,
        "Time": 1521691200000
    }
    
  • 如何使用一个策略 在本地回测引擎中回测

# !/usr/local/bin/python
# -*- coding: UTF-8 -*-
'''backtest
start: 2018-02-19 00:00:00
end: 2018-03-22 12:00:00
period: 15m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD","balance":10000,"stocks":3}]
'''
import sys
sys.path.append("/usr/local/lib/python2.7/site-packages")    # 测试时添加了路径,如不需要可以删除

from fmz import *
import math
import talib

task = VCtx(__doc__) # initialize backtest engine from __doc__

# ------------------------------ 策略部分开始 --------------------------
print exchange.GetAccount()     # 调用一些接口,打印其返回值。
print exchange.GetTicker()

def adjustFloat(v):             # 策略中自定义的函数
    v = math.floor(v * 1000)
    return v / 1000

def onTick(e):
    Log("onTick")
    # ....

#
# ...
# 
# 此处省略 自定义函数实现等代码。

def main():
    InitAccount = GetAccount()
    
    while True:
        onTick(exchange)
        Sleep(1000)
# ------------------------------ 策略部分结束 --------------------------

try:
    main()                     # 回测结束时会 raise EOFError() 抛出异常,来停止回测的循环。所以要对这个异常处理,在检测到抛出的异常后调用 task.Join() 打印回测结果。
except:
    print task.Join()          # print backtest result  , 打印回测结果。

More

alextao /Users/taoxing/opt/anaconda3/envs/ai4f/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py:793: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning. warnings.warn(FSADeprecationWarning( Traceback (most recent call last): File "/Users/taoxing/Desktop/quant/trading_api_study/fmz/fmz_extend_api_demo/app.py", line 152, in <module> db.create_all() File "/Users/taoxing/opt/anaconda3/envs/ai4f/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py", line 963, in create_all self._execute_for_all_tables(app, bind, 'create_all') File "/Users/taoxing/opt/anaconda3/envs/ai4f/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py", line 955, in _execute_for_all_tables op(bind=self.get_engine(app, bind), **extra) File "/Users/taoxing/opt/anaconda3/envs/ai4f/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py", line 896, in get_engine return connector.get_engine() File "/Users/taoxing/opt/anaconda3/envs/ai4f/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py", line 556, in get_engine self._sa.apply_driver_hacks(self._app, info, options) File "/Users/taoxing/opt/anaconda3/envs/ai4f/lib/python3.8/site-packages/flask_sqlalchemy/__init__.py", line 861, in apply_driver_hacks info.database = os.path.join(app.root_path, info.database) AttributeError: can't set attribute 错在什么地地方了,求大神指导!!!

guanyuwanglei 我想运行实盘机器人,添加Wex.app交易所相当于实盘模拟交易是吧?谢谢

guanyuwanglei 但是实盘回测的数据只有一点,还可以优化哪些设置,获取更多实盘数据呢? /upload/asset/105f604eaceb0d3928a90.png /upload/asset/1066714d9a32c82eab7f1.png

guanyuwanglei 您好,我想使用火币现货husd/usdt交易对, 我试了exchange.IO("currency", "HUSD_USDT"),exchange.IO("currency", "HUSD/USDT"),exchange.IO("currency", "HUSDUSDT"),不是运行退出就是品种订阅失败,请问正确的写法是什么?谢谢

每日一嫩模 这回测的结果看不懂啊,怎么可视化呢。

guanyuwanglei 请问, 在windows系统,exchange 找不到怎么解决,谢谢

woshiyituoshi 目前回测系统支持的交易对比较少,这个开源项目是否允许自己开发添加一些交易对?

1058715329 什么时候可以支持本地的参数优化?

一叶行知 @小小梦 谢谢。有python3的模版么?我已经下载了fmz的库,但使用的时候报错,找不到包在哪。 /upload/asset/1042a0deeb6624376f8fb.png

weis 如何设置Tick模式?默认貌似用的是模拟级Tick,怎么切换到实盘级Tick

sxiaojian 还是不会用,一个策略的main函数应该放在这个例子里的什么地方

sxiaojian 回测只能用LTC_BTC吗?我改成BTC_USDT程序就报错了

teddy print exchange.GetTicker() 在 python3 中是不是应该写成print (exchange.GetTicker())?

yxybyq 在平台回测没问题,本地回测经常报错

liput 在fmz中是自己写main函数,看到大多数策略都是自己写while True,然后一直循环调用策略的。但是在使用python的本地回测引擎时,while True会一直让程序运行,无法在__doc__指定的起始时间和结束时间内停止运行,并给出Log的输出。这时候应该怎么办? 另外,我在其他的量化平台看到一般都是只由开发者编写指定的函数,然后由平台回调。fmz允许直接编写main入口,是有什么设计上或架构上的优势或考虑吗?

liput 代码中的交互输入变量,怎么写在__doc__里面,或者是作为参数输入呢?

liput 代码已经改成fmz了,文档里面的示例代码要改一下package名。

YesYes main()里是正常的 在class里call exchange会报错,原因是?   File "D:/workspace/strategy/strategy_001.py", line 101, in main     account = self._exchange.GetAccount()   File "C:\Users\User\AppData\Local\Programs\Python\Python36-32\lib\site-packages\botvs.py", line 716, in GetAccount     EOF()   File "C:\Users\User\AppData\Local\Programs\Python\Python36-32\lib\site-packages\botvs.py", line 569, in EOF     raise EOFError()

topscien 这个东西的作用是什么?没看懂哦

Lizza 没太看明白怎么用的,这个本地回测还需要跟botvs平台通信嘛?回测哪个策略是在哪里设置的呢?

小小梦 用最新的 fmz包试下。

小小梦 托管者是免费使用的,但是一键部署是自动租用阿里云的服务器,这个费用是服务器的费用。一键部署好,做实盘或者模拟盘都行。

guanyuwanglei 这个明白,就是托管者付费,运行机器人可以选择wexApp进行测试,也可以选择真实交易所实盘交易,对吧

小小梦 一件部署托管者,是部署在阿里云服务器上,是付费的,会从你的账号余额中计费。 机器人运行,只操作wexApp模拟盘,机器人费用是不计费的,和一件部署托管者服务器费用无关。

guanyuwanglei 就是说,一键部署服务器,可以选择WexApp,机器人与模拟交易所,测试一下模拟效果, 是这样吧?

小小梦 这个一键部署租用的服务器是其它另外的计费。和机器人实盘费用无关,使用wexApp模拟盘只是说机器人运行免费(数字货币机器人添加了任意一个非WexApp模拟盘交易所对象都会计费)。

guanyuwanglei 一键租用托管者,使用wexApp交易所不计费? /upload/asset/1066e4b56fa103356dbc1.png

小小梦 wexApp是FMZ的模拟盘,不计费的。

小小梦 不客气。

小小梦 实盘级别回测数据量比较大, 图上设置已经是最优了。

guanyuwanglei 改为了最近时间段,设置为ok交易对, exchange.SetCurrency("BTC_USDT") ,可以实盘了,非常感谢

小小梦 换最近的时间段试下。

guanyuwanglei /upload/asset/1063627010637fee333ad.png 代码里面这样设置exchange.SetCurrency("BTC_USDT") 但总提示“品种订阅失败 BTC_USDT_OKEX” 或者什么都不显示,直接退出

guanyuwanglei 谢谢

小小梦 实盘可以的,平台线上回测和本地回测引擎用的都是FMZ数据中心的数据,提供有限的交易对数据,并非全部的交易对都有。

guanyuwanglei 真实交易可以获取此交易对吗?

小小梦 回测系统暂时没有这个交易对的数据。

小小梦 回测结果是个数据形式,如果要可视化要自己写代码解析。如果不会,就用线上的回测系统就可以了。

guanyuwanglei A5:=MA(C,5); A10:=MA(C,10);夹角:IF(CROSS(A5,A10),ATAN((A5/REF(A5,1)-1)*100)-ATAN((A10/REF(A10,1)-1)*100),0)*180/3.1416; 找到了这个公式,就是不知道REF如何实现

小小梦 这个要根据需求,在策略里面计算了,公式可以百度搜索下,找下。

guanyuwanglei 请问如何计算macd金叉\死叉角度,有没有计算公式?谢谢

guanyuwanglei 请问,在策略编辑器里面import statsmodels 无效,请问在那里可以导入第三方库?我在pycharm里可以导入,但是在编辑器里如何导入?

小小梦 这个是固定的K线起始时间,如果需要从零点开始的日K线,可以用一小时K线合成计算。

guanyuwanglei 请问,代码里的收盘时间与回测的收盘都是北京时间早上8:00吗? 如果收盘时间不是早上8:00,请问如何设置, 谢谢 /upload/asset/1067eabe09e92d1610d71.png

小小梦 可以在策略广场上找一些策略例子看了,如果能全部看明白,就可以动手写一些简单策略了。

guanyuwanglei 请问,我初级教材、FMZ使用方法、api文档都看完了,接下来应该看那些知识?,谢谢

小小梦 不客气。

guanyuwanglei 谢谢

小小梦 这个直接在命令行运行就可以。

guanyuwanglei 这段代码我在.py文件运行时,需要导入ccxt,否则exchange无法识别。 在 Python Consle编辑,则可以正常运行。

小小梦 不用的,普通python程序就能跑。我上面的代码就是直接命令行跑的。

guanyuwanglei /upload/asset/106d6ff1919bdac419875.png 导入ccxt的 exchange 竟然可以了,fmz里面用到了ccxt?,没发现呀?

小小梦 刚才测试了下: 文件名testBackTest ``` from fmz import * task = VCtx('''backtest start: 2018-02-19 00:00:00 end: 2018-03-22 12:00:00 period: 15m exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}] ''') # create backtest print(exchange.GetAccount()) print(exchange.GetTicker()) ``` /upload/asset/16bea6055e58a9ef7d5c.png

小小梦 更新最新版的 fmz python 包试下,我刚下载测试的。

guanyuwanglei /upload/asset/1068d63bc6203599fc1c8.png 修改完初始化,但是exchange、Log还是无法识别

小小梦 ``` from fmz import * task = VCtx('''backtest start: 2018-02-19 00:00:00 end: 2018-03-22 12:00:00 period: 15m exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}] ''') # 创建回测环境 ``` 这样初始化一下,就好比在线回测的时候配置上了 交易所 、交易对 等信息。

guanyuwanglei /upload/asset/106581e23604bb2d701d8.jpg exchange 无法识别,已经在python里面安装fmz包了

小小梦 具体报错截图看下。

小小梦 暂时不行, 因为回测数据是从FMZ获取的。不过代码是开源的,可以随意修改,替换掉数据源。

小小梦 ``` /*backtest start: 2019-09-21 00:00:00 end: 2019-10-20 00:00:00 period: 1h exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}] mode: 1 */ ``` 通过配置信息中的,```mode``` 设置,可以在回测页面上设置,然后在策略编辑页面上直接保存回测设置获取到配置信息字符串。

Posteriori 同问?

chujiu 对的

xenide

小小梦 好的 ,这个记录下,暂时没有支持。

一叶行知 好的,谢谢。

小小梦 找到问题了,正在处理。

一叶行知 是的,mac os 10.14.4

小小梦 您的操作系统是 Mac OSX么

一叶行知 我是用conda进行python版本管理的,我确认已经下载了fmz的python版本,本地也有了。但看官网上是写的支持python3的,但我去尝试的时候就出现这问题了。是我代码写错了么?我不知道exchange这个对象哪里来的,Log也无法找到。

小小梦 您是不是有多个 python 版本,检查下 看这个包安装到哪里了。

小小梦 帖子已经更新,您可以看下帖子最后的 范例。

小小梦 main 函数写好, 直接 调用就行了。

sxiaojian https://github.com/fmzquant/backtest_python/issues/4,看看这个有没有帮助

小小梦 错误信息 ,具体 可以截图看下。

sxiaojian 就是示例代码改成BTC_USDT就出错

小小梦 这个要看是 选择的是 哪个交易所 回测。

小小梦 要具体看下 报错信息 ,看下是错误位置。

小小梦 FMZ 采用的是 轮询架构 ,这样对于 程序 流程掌控力更强一点,编写策略更加灵活。

小小梦 '''backtest start: 2018-02-19 00:00:00 end: 2018-03-22 12:00:00 period: 15m exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}] ''' 这些 就是

小小梦 修改了一下。

小小梦 文件 开始 加载 这个 模拟账户配置 , 如果写在 类里面 是不是 加载不到了。

YesYes 这配置应该是对的吧 为什么不能写进class引用

YesYes 回测账户数据,是下面几行吗? 有喔,在global function main里正常引用。 可是在class里却报错 '''backtest start: 2018-02-19 00:00:00 end: 2018-03-22 12:00:00 period: 15m exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}] ''' from botvs import * task = VCtx(__doc__) # initialize backtest engine from __doc__

小小梦 ``` def GetAccount(self): r = _ACCOUNT() ret = self.lib.api_Exchange_GetAccount(self.ctx, self.idx, ctypes.byref(r)) if ret == API_ERR_SUCCESS: return r.toObj() elif ret == API_ERR_FAILED: return None EOF() ``` 看了下代码 好像 api_Exchange_GetAccount 这个是一个 DLL 的接口, 您上面报错信息 显示 没有返回 调用成功 也没有返回调用失败, 然后就去执行 EOF 了。您 使用回测引擎 时 有配置 回测账户 数据么?

小小梦 就是 把回测系统 打包成一个 python 库了, 可以让 本地 python 进行策略 回测。

小小梦 会有 通信,回测时是有数据请求的,不过运行是在本地跑的回测系统。 ``` '''backtest start: 2018-02-19 00:00:00 end: 2018-03-22 12:00:00 period: 15m exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}] ''' from botvs import * task = VCtx(__doc__) # initialize backtest engine from __doc__ print exchange.GetAccount() print exchange.GetTicker() print task.Join() # print backtest result ``` 这个段代码 就类似 一个 策略, 回测系统 被封装成一个 库了, 测试 运行的时候 调用回测系统的功能。 上面的 '''backtest ... ''' 内的 就是 回测参数设置, 可以在BotVS 策略回测页面生成。