我们之前在喂历史资料,都是先用 shioaji 下载下来,然後再用 padas 转成 dataframe,最後再喂给 backtrader,在 backtrader 里的 datafeeds 也是可以自订义的,有几个步骤:
params = (('dataname', None),
('fromdate', datetime.datetime.min),
('todate', datetime.datetime.max),
('name', ''),
('compression', 1),
('timeframe', TimeFrame.Days),
('sessionend', None))
以下我就用 Shioaji 取得资料来示范
import backtrader as bt
import backtrader.feeds as btfeeds
from backtrader import date2num
import shioaji as sj
from datetime import datetime
class ShioajiFeeds(bt.feed.DataBase):
params = (
("person_id", "身份证字号"),
("passwd", "永丰金证券密码"),
("start", datetime.now().strftime("%Y-%m-%d")),
("end", datetime.now().strftime("%Y-%m-%d")),
("stock", "2330"),
# 这个变数是 DataBase 的
# 因为 Shioaji 取得的资料是每分钟,所以设成 TimeFrame.Minutes
("timeframe", bt.TimeFrame.Minutes),
)
def start(self):
self.api = sj.Shioaji()
self.api.login(person_id = self.p.person_id, passwd = self.p.passwd)
contract = self.api.Contracts.Stocks[self.p.stock]
self.kbar = self.api.kbars(contract, start = self.p.start, end = self.p.end)
self.idx = 0
self.dataLength = len(self.kbar.ts) # 纪录我们取得的资料有多少笔
def _load(self):
# 资料会一笔一笔读进来,如果读到最後一笔,就跳出 False
if (self.idx == self.dataLength):
return False
dt = datetime.utcfromtimestamp(self.kbar.ts[self.idx] / 10**9)
self.lines.datetime[0] = date2num(dt)
self.lines.open[0] = self.kbar.Open[self.idx]
self.lines.high[0] = self.kbar.High[self.idx]
self.lines.low[0] = self.kbar.Low[self.idx]
self.lines.close[0] = self.kbar.Close[self.idx]
self.lines.volume[0] = self.kbar.Volume[self.idx]
self.idx += 1
return True
def stop(self):
# 结束的时候进行登出
self.api.logout()
self.api = None
# 使用自订的 datafeed
cerebro = bt.Cerebro()
data = ShioajiFeeds(start='2021-10-01', end='2021-10-08', stock='2303')
cerebro.resampledata(data, timeframe=bt.TimeFrame.Days)
cerebro.addstrategy(bt.Strategy)
cerebro.run()
cerebro.plot()
那如果我们要载入多笔股票的资料,以这个写法,需要进行登入登出多次,所以可以稍微改一下,把 api 当成一个参数去执行
class ShioajiFeeds(bt.feed.DataBase):
params = (
("person_id", "身份证字号"),
("passwd", "永丰金证券密码"),
("start", datetime.now().strftime("%Y-%m-%d")),
("end", datetime.now().strftime("%Y-%m-%d")),
("stock", "2330"),
("timeframe", bt.TimeFrame.Minutes),
("api", None), # 新增一个 api 参数
)
def start(self):
if self.p.api is None:
self.api = sj.Shioaji()
self.api.login(person_id = self.p.person_id, passwd = self.p.passwd)
else:
self.api = self.p.api
# ...略
def stop(self):
if self.p.api is None:
self.api.logout()
self.api = None
在执行的时候,我们就可以先初始化 api,然後把 api 当参数传入,就可以不用一直登入登出了
api = sj.Shioaji()
api.login(person_id = "帐号", passwd = "密码")
data = ShioajiFeeds(start = '2021-10-01', end = '2021-10-08', stock = '2330', api = api)
# ... 略
# 结束後,记得登出
api.logout()
<<: Day23 :【TypeScript 学起来】先了解 ES6 Class
>>: [Day 23] 阿嬷都看得懂的进阶 CSS 选择器与伪类选择器
Doc https://cloud.google.com/storage/docs/storage-...
Core Data 官方文件 Core Data 是 iOS 的资料库,可让使用者在本地端储存资料 ...
先发 jserv 的 2021 年「资讯科技产业专案设计」课程又开始了, 课程内容就是教怎麽面资讯...
Data层的任务主要是储存Object的component,保证资料的安全,他和API层一样也有AP...
深度优先搜寻(depth-first search, DFS)是一种搜寻整张图所有节点的演算法。它的...