D:\vnstudio\lib\site-packages\vnpy\app\cta_strategy\backtesting.py:399: RuntimeWarning: invalid value encountered in log
df["return"] = np.log(df["balance"] / df["balance"].shift(1)).fillna(0)
策略回测,出现上述错误 ,请帮忙看一下,谢谢
我使用的是
(1)VPNY 2.5.4
(2)数据库使用mongodb
(3)为了加快读取速度,使用了每个标的保存至 指定的 Collection(一个股票保存到 一个Collection)
是根据帖子 https://www.vnpy.com/forum/topic/3131-vn-pyshe-qu-jing-xuan-19-fu-yin-shou-wei-mongodbfen-biao-shu-ju-du-qu
对VPNY进行了修改
请问,在实盘运行策略
如果策略中
def on_init(self):
self.write_log("策略初始化")
self.load_bar(120)
(1)self.load_bar(120) 是从 接口读取数据,并合成bar, 还是从数据库读取 ?
(2)如果mongodb数据库中,保存的数据是 bar 或者 是 tick ,策略读取的情况是怎么样的 ?
(3)如上面所述,对VNPY进行了修改,每个标的数据 保存至 指定的 Collection,是否影响实盘的数据读取,如果影响,如何进行修改 ?
谢谢
请问一下,使用VPNY对A股,进行回测,如何实现T +1 , 谢谢!
在我的另外一个帖子(链接;https://www.vnpy.com/forum/topic/4699-yong-portfolio-strategymo-kuai-xie-de-duo-biao-de-shuang-jun-xian-ce-lue-huan-you-gu-piao-chi-de-wen-ti?page=1#pid16330)
打算按照一定的规则,建立一个 股票池,股票池的 股票标的,和数量,过一段时间,就会改变
设想在 策略之外,对所有股票进行 筛选,赋值给 engine.set_parameters的 vt_symbols
但在 策略中,比如 双均线策略(有2个标的 )
class DemoStrategy2(StrategyTemplate):
# 第一个标的的 快速均线,和慢速均线
fast_window_1 = 10
slow_window_1 = 20
fast_ma0_1 = 0.0
fast_ma1_1 = 0.0
slow_ma0_1 = 0.0
slow_ma1_1 = 0.0
# 第二个标的的 快速均线,和慢速均线
fast_window_2 = 10
slow_window_2 = 20
fast_ma0_2 = 0.0
fast_ma1_2 = 0.0
slow_ma0_2 = 0.0
slow_ma1_2 = 0.0
def init(....)
super().init(.....)
self.bg = BarGenerator(self.on_bar)
self.am_1 = ArrayManager()
self.am_2 = ArrayManager()
def on_bar(self, bar: BarData):
bars = {bar.vt_symbol: bar}
self.on_bars(bars)
def on_bars(self, bars: Dict[str, BarData]):
""""""
self.cancel_all()
bar_1 = bars[self.vt_symbol_1]
am_1 = self.am_1
am_1.update_bar(bar_1)
if not am_1.inited:
return
bar_2 = bars[self.vt_symbol_2]
am_2 = self.am_2
am_2.update_bar(bar_2)
if not am_2.inited:
return
象以上的 不同标的的 快慢速均线, 在标的数量不确定的情况下 ;
bar 生成器 BarGenerator
序列生成器 ArrayManager()
在 init , on_bar , on_bars
如何写,才更简便,灵活 ?
才能更好的 ,配合 多标的
谢谢大家
一个用portfolio_strategy模块,写的 多标的 双均线策略,有2个标的,策略的数据源是 mongodb,不同的标的使用,不同的表
(1)请大家看看,有什么地方可以修改,优化,简洁一些 ?
我指的优化,不是指策略本身,意思指,在使用 portfolio_strategy模块方面,有什么改善的地方?
(2)如果建立股票池,股票池的 标的和数量 ,过一段时间就会改变,使用portfolio_strategy模块,策略怎么样写?
谢谢大家
from vnpy.app.cta_strategy.backtesting import BacktestingEngine
from datetime import datetime
from importlib import reload
import vnpy.app.portfolio_strategy
reload(vnpy.app.portfolio_strategy)
from vnpy.app.portfolio_strategy import BacktestingEngine
import vnpy.app.portfolio_strategy.strategies.pair_trading_strategy as stg
reload(stg)
from vnpy.trader.constant import Interval, Direction, Offset
from typing import List, Dict
from vnpy.trader.object import BarData, TickData, OrderData, TradeData
from vnpy.app.portfolio_strategy import StrategyTemplate, StrategyEngine
from vnpy.trader.utility import BarGenerator, ArrayManager
from vnpy.trader.object import TickData, BarData
engine = BacktestingEngine()
engine.set_parameters(
vt_symbols=["000001.SZSE","601518.SSE"],
interval=Interval.MINUTE,
start=datetime(2017, 7, 1),
end=datetime(2020, 9, 21),
rates={"000001.SZSE": 0/10000,"601518.SSE": 0/10000},
slippages={"000001.SZSE": 00,"601518.SSE": 0},
sizes={"000001.SZSE": 10,"601518.SSE": 10},
priceticks={"000001.SZSE": 1,"601518.SSE": 1},
capital=1_000_000,
collection_names={"000001.SZSE":'000001_bar',"601518.SSE":'601518_bar'}
)
class DemoStrategy2(StrategyTemplate):
""""""
author = "zhp168"
fast_window_1 = 10
slow_window_1 = 20
fast_ma0_1 = 0.0
fast_ma1_1 = 0.0
slow_ma0_1 = 0.0
slow_ma1_1 = 0.0
fast_window_2 = 10
slow_window_2 = 20
fast_ma0_2 = 0.0
fast_ma1_2 = 0.0
slow_ma0_2 = 0.0
slow_ma1_2 = 0.0
parameters = ["fast_window","slow_window"]
variables = ["fast_ma0","fast_ma1","slow_ma0","slow_ma1"]
def __init__(
self,
strategy_engine: StrategyEngine,
strategy_name: str,
vt_symbols: List[str],
setting: dict
):
""""""
super().__init__(strategy_engine, strategy_name, vt_symbols, setting)
self.bg = BarGenerator(self.on_bar)
self.am_1 = ArrayManager()
self.am_2 = ArrayManager()
self.vt_symbol_1 = vt_symbols[0]
self.vt_symbol_2 = vt_symbols[1]
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bars(20)
def on_start(self):
"""
Callback when strategy is started.
"""
self.write_log("策略启动")
def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log("策略停止")
def on_tick(self, tick: TickData):
"""
Callback of new tick data update.
"""
self.bg.update_tick(tick)
def on_bar(self, bar: BarData):
"""
Callback of new bar data update.
"""
bars = {bar.vt_symbol: bar}
self.on_bars(bars)
def on_bars(self, bars: Dict[str, BarData]):
""""""
self.cancel_all()
bar_1 = bars[self.vt_symbol_1]
am_1 = self.am_1
am_1.update_bar(bar_1)
if not am_1.inited:
return
bar_2 = bars[self.vt_symbol_2]
am_2 = self.am_2
am_2.update_bar(bar_2)
if not am_2.inited:
return
# 第一个标的,计算快速均线
fast_ma_1 = am_1.sma(self.fast_window_1, array=True)
self.fast_ma0_1 = fast_ma_1[-1] # T时刻数值
self.fast_ma1_1 = fast_ma_1[-2] # T-1时刻数值
# 第二个标的,计算快速均线
fast_ma_2 = am_2.sma(self.fast_window_2, array=True)
self.fast_ma0_2 = fast_ma_2[-1] # T时刻数值
self.fast_ma1_2 = fast_ma_2[-2] # T-1时刻数值
# 第一个标的,计算慢速均线
slow_ma_1 = am_1.sma(self.slow_window_1, array=True)
self.slow_ma0_1 = slow_ma_1[-1]
self.slow_ma1_1 = slow_ma_1[-2]
# 第二个标的,计算慢速均线
slow_ma_2 = am_2.sma(self.slow_window_2, array=True)
self.slow_ma0_2 = slow_ma_2[-1]
self.slow_ma1_2 = slow_ma_2[-2]
# 获取仓位
pos_1 = self.get_pos(self.vt_symbol_1)
pos_2 = self.get_pos(self.vt_symbol_2)
# 判断是否金叉
cross_over_1 = (self.fast_ma0_1 > self.slow_ma0_1 and
self.fast_ma1_1 < self.slow_ma1_1)
cross_over_2 = (self.fast_ma0_2 > self.slow_ma0_2 and
self.fast_ma1_2 < self.slow_ma1_2)
# 判断是否死叉
cross_below_1 = (self.fast_ma0_1 < self.slow_ma0_1 and
self.fast_ma1_1 > self.slow_ma1_1)
cross_below_2 = (self.fast_ma0_2 < self.slow_ma0_2 and
self.fast_ma1_2 > self.slow_ma1_2)
# 如果发生了金叉
if cross_over_1:
# 为了保证成交,在K线收盘价上加5发出限价单
price = bar_1.close_price + 5
# 当前无仓位,则直接开多
if pos_1 == 0:
self.buy(self.vt_symbol_1,price, 1)
# 当前持有空头仓位,则先平空,再开多
elif pos_1 < 0:
self.cover(self.vt_symbol_1,price, 1)
self.buy(self.vt_symbol_1,price, 1)
# 如果发生了死叉
elif cross_below_1:
price = bar_1.close_price - 5
# 当前无仓位,则直接开空
if pos_1 == 0:
self.short(self.vt_symbol_1,price, 1)
# 当前持有空头仓位,则先平多,再开空
elif pos_1 > 0:
self.sell(self.vt_symbol_1,price, 1)
self.short(self.vt_symbol_1,price, 1)
# 如果发生了金叉
if cross_over_2:
# 为了保证成交,在K线收盘价上加5发出限价单
price = bar_2.close_price + 5
# 当前无仓位,则直接开多
if pos_2 == 0:
self.buy(self.vt_symbol_2, price, 1)
# 当前持有空头仓位,则先平空,再开多
elif pos_2 < 0:
self.cover(self.vt_symbol_2, price, 1)
self.buy(self.vt_symbol_2, price, 1)
# 如果发生了死叉
elif cross_below_2:
price = bar_2.close_price - 5
# 当前无仓位,则直接开空
if pos_2 == 0:
self.short(self.vt_symbol_2, price, 1)
# 当前持有空头仓位,则先平多,再开空
elif pos_2 > 0:
self.sell(self.vt_symbol_2, price, 1)
self.short(self.vt_symbol_2, price, 1)
self.put_event()
def update_trade(self, trade: TradeData):
print("股票编号:", trade.symbol, "成交时间:", trade.datetime, "成交价格:", trade.price)
print("方向:", trade.direction, trade.direction.value, "offset:", trade.offset, "成交量:", trade.volume)
engine.add_strategy(DemoStrategy2,{})
engine.load_data()
engine.run_backtesting()
df = engine.calculate_result()
engine.calculate_statistics()
engine.show_chart()
请问,VNPY 2.5.1 ,CSV 文件导入功能,在哪里找到 ?谢谢!