IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Backtrader量化&回测3——读取SQL数据(以SQL lite数据库为例) -> 正文阅读

[大数据]Backtrader量化&回测3——读取SQL数据(以SQL lite数据库为例)

读取pandas数据 官方文档:https://www.backtrader.com/docu/pandas-datafeed/pandas-datafeed/

DataFeed 开发 官方文档:https://www.backtrader.com/docu/datafeed-develop-general/datafeed-develop-general/

SQL读取类

官方暂时没有一键读取的功能类,因此需要自己写,一个简单的例子如下,运用请参考最下面的示例代码:

class SQLiteData(DataBase):
    """自定义的SQL lite数据格式"""
    params = (
        ('dataname', None),  # 策略中读取数据库是用到的名称
        ('name', ''),  # 绘图时用到的名称
        ('timeframe', TimeFrame.Days),  # 每条K线代表的时间长短
        ('fromdate', None),  # 从什么时候开始
        ('todate', None),  # 到什么时候截止
    )

    def __init__(self):
        self.engine = create_engine('sqlite:///local_sql_lite.db')  # 初始化数据库连接
        self.tabel_name = "my_stock_code"  # 数据表名称

    def start(self):  # 只会在加载数据前执行一次,常用于初始化参数
        self.conn = self.engine.connect()
        sql_query = "SELECT `date`,`open`,`high`,`low`,`close`,`volume`,`turnover` FROM `{}` ORDER BY `date` ASC" \
            .format(self.tabel_name)
        self.result = self.conn.execute(sql_query)

    def stop(self):  # 结束数据加载程序之后执行一次,常用于关闭数据库链接
        self.engine.dispose()

    def _load(self):  # 类似于策略的 next(),预期执行几次 next(),就会执行几次 _load()
        one_row = self.result.fetchone()
        if one_row is None:
            return False
        self.lines.datetime[0] = date2num(dt.datetime.strptime(str(one_row[0]), '%Y-%m-%d %H:%M:%S'))  # date parsing
        self.lines.open[0] = float(one_row[1])
        self.lines.high[0] = float(one_row[2])
        self.lines.low[0] = float(one_row[3])
        self.lines.close[0] = float(one_row[4])
        self.lines.volume[0] = int(one_row[5])
        self.lines.turnover[0] = float(one_row[6])
        self.lines.openinterest[0] = -1
        return True

其中有几个比较重要的函数:

  • def start():在加载数据前执行一次,常用于初始化参数
  • def stop():结束数据加载程序之后执行一次,常用于关闭数据库链接
  • def _load():在策略中的next()拿到的数据其实就是这里传过去的数据,会循环执行多次这个函数,直到取得全部数据或接收到FalseNone的返回值
  • params:这是定义数据集本身的一些参数,重要参数已在示例代码中解释,更多参数请参考官网

注意:def _load() 函数中:

  • self.lines:表示第一个数据集的列,等同于 self.datas[0].lines,是一种简写形式
  • self.lines.open:指代数据中的开盘价那一列
  • self.lines.open[0]:特指当天的开盘价,如果是self.lines.open[-1],就是昨天的,如果是self.lines.open[1] 就是明天的

示例代码

import backtrader
import efinance
import pandas as pd
from datetime import datetime
import sqlite3
import datetime as dt
from backtrader import TimeFrame
from backtrader.feed import DataBase
from backtrader import date2num
from sqlalchemy import create_engine


def get_k_data(stock_code, begin: datetime, end: datetime) -> pd.DataFrame:
    """根据efinance工具包获取股票数据
    :param stock_code:股票代码
    :param begin: 开始日期
    :param end: 结束日期
    """
    # stock_code = '600519'  # 股票代码,茅台
    k_dataframe: pd.DataFrame = efinance.stock.get_quote_history(
        stock_code, beg=begin.strftime("%Y%m%d"), end=end.strftime("%Y%m%d"))
    k_dataframe = k_dataframe.iloc[:, :9]
    k_dataframe.columns = ['name', 'code', 'date', 'open', 'close', 'high', 'low', 'volume', 'turnover']
    k_dataframe.index = pd.to_datetime(k_dataframe.date)
    k_dataframe.drop(['name', 'code', "date"], axis=1, inplace=True)
    return k_dataframe


def write_sql_lite_from_pandas(stock_code, begin: datetime, end: datetime):
    """获取K线数据,并保存到SQL lite数据库"""
    conn = sqlite3.connect('local_sql_lite.db')
    dataframe = get_k_data(stock_code, begin=begin, end=end)
    dataframe.to_sql("my_stock_code", conn, if_exists="replace")  # 保存数据到数据库中,表名称:my_stock_code


class SQLiteData(DataBase):
    """自定义的SQL lite数据格式"""
    params = (
        ('dataname', None),  # 策略中读取数据库是用到的名称
        ('name', ''),  # 绘图时用到的名称
        ('timeframe', TimeFrame.Days),  # 每条K线代表的时间长短
        ('fromdate', None),  # 从什么时候开始
        ('todate', None),  # 到什么时候截止
        # 下面是除了默认的open,close,high,low,volume外,新添加的维度
        ('turnover', -1),
    )

    # 新添加数据列用法相同
    lines = ('turnover',)

    def __init__(self):
        self.engine = create_engine('sqlite:///local_sql_lite.db')
        self._timeframe = self.p.timeframe
        self._compression = self.p.compression
        self._dataname = "my_stock_code"

    def start(self):
        self.conn = self.engine.connect()
        sql_query = "SELECT `date`,`open`,`high`,`low`,`close`,`volume`,`turnover` FROM `{}` ORDER BY `date` ASC" \
            .format(self._dataname)
        self.result = self.conn.execute(sql_query)

    def stop(self):
        self.engine.dispose()

    def _load(self):
        # 会全部循环完毕,然后再读取
        one_row = self.result.fetchone()
        if one_row is None:
            return False
        self.lines.datetime[0] = date2num(dt.datetime.strptime(str(one_row[0]), '%Y-%m-%d %H:%M:%S'))  # date parsing
        self.lines.open[0] = float(one_row[1])
        self.lines.high[0] = float(one_row[2])
        self.lines.low[0] = float(one_row[3])
        self.lines.close[0] = float(one_row[4])
        self.lines.volume[0] = int(one_row[5])
        self.lines.turnover[0] = float(one_row[6])
        self.lines.openinterest[0] = -1
        return True


class MyStrategy1(backtrader.Strategy):  # 策略
    def __init__(self):
        # 初始化交易指令、买卖价格和手续费
        self.close_price = self.datas[0].close  # 这里加一个数据引用,方便后续操作
        this_data = self.getdatabyname("stock_600519")  # 获取传入的 name = stock_600519 的数据
        print("全部列名:", this_data.getlinealiases())  # 全部的列名称

    def next(self):  # 框架执行过程中会不断循环next(),过一个K线,执行一次next()
        print('=======================')
        print("今天是:", self.datetime.date())
        print("当前的值:", dict(zip(self.datas[0].getlinealiases(), [i[0] for i in list(self.datas[0].lines)])))


def main():
    # 获取数据
    start_time = datetime(2015, 1, 1)
    end_time = datetime(2015, 1, 10)
    # 先保存数据到 SQL lite 数据库,用于后续的读取
    write_sql_lite_from_pandas("600519", start_time, end_time)
    # 从SQL lite数据库读取数据
    data = SQLiteData()
    # =============== 为系统注入数据 =================
    # 加载数据
    # data = PandasDataPlus(dataname=dataframe, fromdate=start_time, todate=end_time)
    # 初始化cerebro回测系统
    cerebral_system = backtrader.Cerebro()  # Cerebro引擎在后台创建了broker(经纪人)实例,系统默认每个broker的初始资金量为10000
    # 将数据传入回测系统
    cerebral_system.adddata(data, name="stock_600519")  # 导入数据,在策略中使用 self.datas 来获取数据源
    # 将交易策略加载到回测系统中
    cerebral_system.addstrategy(MyStrategy1)
    # =============== 系统设置 ==================
    # 运行回测系统
    cerebral_system.run()


if __name__ == '__main__':
    main()
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-08 08:10:56  更:2022-05-08 08:14:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:43:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码