以下内容皆参考 Backtrader 官网
昨天使用了 backtrader 将 shioaji 的历史资料载入,今天我们就做一个很简单的策略来测试实际回测看看
class TestStrategy(bt.Strategy):
def log(self, txt, dt=None):
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def __init__(self):
self.dataclose = self.datas[0].close
def next(self):
self.log('收盘价: %.2f' % dataclose[0])
我们使用 pandas.DataFrame 将 shioaji 的资料载入到 backtrader 的 datas 里,所以 self.datas[0] 就是我们载入的资料,载入的资料有 close, high, low, open, volume,这 5 条线,如果把 datetime 也算进来的话,那就是 6 条线。
在 init 里,我们把 close 这一条线特别设了一个变数叫 self.dataclose,然後在 next 这个函数里,我们将 dataclose[0] 的数值输出来。
回测就是从最旧的资料,一笔一笔往最新的资料跑,所以这个 dataclose[0] 就是目前程序跑到的那一笔,如果要看前一笔,就是 dataclose[-1], 以此类推,可以是 -2, -3 前两笔,前三笔。
以上这段程序就是让它一天一天跑,然後把收盘价输出来
from datetime import datetime
import pandas as pd
import shioaji as sj
import backtrader as bt
api = sj.Shiaji()
api.login(person_id="身分证字号", passwd="密码")
stock2330 = api.Contracts.Stocks["2330"]
kbar2330 = api.kbars(stock2330, start='2020-01-01', end='2020-12-31')
dts = list(map(lambda x:dateime.utcformattimestamp(x/10**9), kbr2330.ts))
df = pd.DataFrame(
{
"open": pd.Series(kbar2330.Open),
"high": pd.Series(kbar2330.High),
"low": pd.Series(kbar2330.Low),
"close": pd.Series(kbar2330.close),
"volume": pd.Series(kbar2330.Volume),
}
)
df.index = pd.Index(dts)
以上为取得资料的程序码,如果是用 jupyter notebook 的话,可以放在一个独立的程序区块,这样就不用一直去抓资料下来了,执行起来会快一些
cerebro = bt.Cerebro()
# 载入要执行的策略
cerebro.addstrategy(TestStrategy)
# 因为台积的股价有点高,所以我们初始资金设 100 万
cerebro.broker.setcash(10**6)
# 券商的手续费
cerebro.broker.setcommission(commission=0.1425/100)
data = bt.feeds.PandasData(dataname=df, timeframe=bt.TimeFrame.Minutes)
cerebro.resampledata(data, timeframe=bt.TimeFrame.Days)
# 如果跑到最後,还有股票没有卖出的话,会以当天收盘价的价格来加总
print("初始资金: %.2f" % cerebro.broker.getvalue())
# 执行策略
cerebro.run()
print("结束资金:%.2f" % cerebro.broker.getvalue())
以上程序,执行之後可以看到输出每天的收盘价,接下来我们来卖加一个买入的策略
class TestStrategy(bt.Strategy):
def log(self, txt, dt=None):
#...略
def __init__(self):
#...略
def next(self):
self.log('收盘价: %.2f' % dataclose[0])
# 当天收盘价比昨天低 -> 跌
if self.dataclose[0] < self.dataclose[-1]:
# 昨天的收盘价比前天低 -> 连跌 2 天
if self.dataclose[-1] < self.dataclose[-2]:
self.log("买入: %.2f" % self.dataclose[0])
# 一张股票是1000股
self.buy(size=1000)
这个策略就是,如果股票连跌 2 天,就买入 1 张 (1000 股),执行完的个策略後,再去跑回测,就可以看到我们买进股票,再来我们要增加卖出的策略
class TestStrategy(bt.Strategy):
def log(self, txt, dt=None):
# ...略
def __init__(self):
# ...略
# 建立一个变数储存我们己经买的股票
self.order = None
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# 买卖单传送到券商,券商接收,无需处理
return
if order.status in [order.Completed]:
# 买卖单交易完成
if order.isbuy():
# 买单
self.log("已买入:%.2f" % order.executed.price)
elif order.issell():
# 卖单
self.log("已卖出:%.2f" % order.executed.price)
# 纪录是在第几笔资料进行交易
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log("交易失败")
# 没有待处理订单
self.order = None
def next(self):
self.log("收盘价:%.2f" % self.dataclose[0])
# 还有未处理的订单,直接跳过
if self.order:
return
# 没有持股 -> 进行买入策略
if not self.position:
if self.dataclose[-1] < self.dataclose[0]:
if self.dataclose[-2] < self.dataclose[-1]:
self.log("买入:%.2f" % self.dataclose[0])
self.order = self.buy(size=1000)
# 有持股 -> 进行卖出策略
else:
if len(self) >= (self.bar_executed + 5):
self.log("卖出:%.2f" % sef.dataclose[0])
self.order = self.sell(size=1000)
这样就是一个简单的买入,卖出策略回测,执行之後,就可以看到以这样子的策略,我们的在 2020 年可以赚到多少,当然因为这个是历史资料,所以只是一个评估,并不代表未来用这个策略去执行也可以获得同样的收益喔
>>: Day 0x18 - 使用 Laravel 串接之结尾及自我检讨
今天开始将进行Python基本语法练习,因大部分语法跟很多程序语言相似,故这个部分将主要以笔记方式注...
凭证请求档制作 本文是在 Windows 环境下操作 下载工程师必备神器 Cmder 最省事,该程序...
呃,首先呢~ 敝人小弟在下我今天仔细的思考了一下,决定这次还是再来一篇『中场休息』科普文,等到明天再...
根据相对论,如果一对挛生兄弟, 哥哥搭乘宇宙飞船,以接近光速,飞离地球,在宇宙间航行; 当回到地球的...
除了功能完善,有时候效能也该一并考虑。 今天要介绍的是 CreateDocumentFragmen...