利用Python进行股票交易分析(三):A股量化交易策略的验证及数据分析。

鉴于近期空闲时间比较少,本篇文章采用不定时更新的方式来写,如大家有更好的思路也可以评论区一起讨论....

目前进度:

2021-07-13 梳理、修改思路

2021-07-14 步骤1代码完成


背景

1、前两篇文章我们分别对股票量化交易策略进行了定义(详见第一篇)、并对A股所有历史行情数据进行了爬取保存以备后续的数据分析(详见第二篇)

第一篇:利用Python进行股票交易分析(一):量化交易策略——买点与卖点的量化

第二篇:利用Python进行股票交易分析(二):爬取A股所有历史行情数

2、策略是否有效可行,我们需要根据大量的历史行情数据来进行回测验证。

目标

1、将量化交易策略用于单个股票进行回测,并将回测结果可视化(策略收益趋势、最大回撤幅度),交易日志展现(交易日期、买入/卖出价格、交易金额、收益情况-金额/幅度)

2、将量化交易策略用于多个股票(可自定义股票池)进行回测,并将回测结果可视化(策略总收益趋势、最大回撤幅度),交易日志展现(交易日期、买入/卖出价格、交易金额、收益情况-金额/幅度)

3、优化策略,若发现原策略有缺陷或收益不符合预期,将进行适当的拟合以达到优化目的。

4、若策略验证可行,则开发自动提醒功能,监测股票池中个股的行情走势,出现买卖点时是自动推送邮件到自己的邮箱(股票名、策略建议-出现买入/卖出点、买入/卖出价格、近日行情趋势参考线)。

实现过程简述

对交易策略进行量化定义→自定义股票池→准备历史行情数据→策略实现→进行回测→数据分析

策略量化定义

买入点定义:当股价在连续下跌行情中,出现某日突破5日均线时,次日以5日均价挂买

即:设某交易日为N,MA5连续下跌天数为X,当N-1至N-X区间的MA5连续下跌,且N收盘价>N的收盘MA5价,则在N+1日以N+1的开盘MA5价挂买,如图:

利用Python进行股票交易分析(三):A股量化交易策略的验证及数据分析。_第1张图片

卖出点定义:当买入后当日的收盘价未站稳5日均线,或买入之后在某日跌破5日均线的,则次日开盘卖出。

即:设买入日为N,卖出日为M,对N及N之后的每个交易日依次检验收盘价是否低于当日收盘后MA5价,若低于则次日卖出,如图:

利用Python进行股票交易分析(三):A股量化交易策略的验证及数据分析。_第2张图片

具体实现

准备:①第二篇文章中所讲的个股历史行情数据已爬取完成②安装本次所需的第三方模块

1、自定义股票池并读取

①创建自定义股票池文件,命名为“stockcodes.csv”,将待回测的股票代码复制到文件当中,本次回测股票池将加入所有A股代码,大家可根据需要自行添加股票代码到股票池文件中,例如:

利用Python进行股票交易分析(三):A股量化交易策略的验证及数据分析。_第3张图片

读取:

#步骤-1
#读取股票池CSV文件,返回stockcodes['600010',...]
def ReadCSV(filename):
    stockcodes = [] #个股代码列表
    count = 0 #个股代码计数
    try:
        with open(filename,'r') as f:
            reader = csv.reader(f)
            for row in reader:
                stockcodes.append(row[0])
                count += 1
        print('读取股票池成功:{}'.format(count))
        re = 1 #请求继续运行
    except:
        print('股票池读取失败,检查文件位置及名称:{}'.format(filename)) 
        re = 0 #请求停止运行
    return stockcodes,re

②读取数据库中的所有个股表名

#读取数据库STOCK中的所有股票数据表 s_code,返回tablenames['s_600010',...]
def ReadTableName(dbinfo):
    tablenames = [] #数据表名列表
    #连接数据库
    try:
        db = pymysql.connect(
            host = dbinfo['host'],
            user = dbinfo['user'],
            password = dbinfo['password'],
            database = dbinfo['dbname'],
            port = dbinfo['port']
        )
        cursor = db.cursor()
        print('数据库连接成功!正在读取表名...')
        re = 1
    except:
        print('数据库连接失败,请检查数据库信息配置!')
        re = 0
    if re :
        sql_showtables = 'show tables'
        cursor.execute(sql_showtables) #查询表名
        for tablename in cursor:
            tablenames.append(tablename[0]) 
        print('数据表名称读取完成!')   

    return tablenames,re     

③检查股票池中个股数据表是否已存在于数据库,若不存在则需要修改股票池或重新爬取数据

#检查股票池中个股数据是否已存在于数据库,返回miss_tablename['600010',...]
def CheckTableName(stockcodes,tablenames):
    re = 1 
    for stockcode in stockcodes:
        s_stockcode = 's_'+stockcode
        if s_stockcode not in tablenames:
            re = 0 #请求中止程序
            print('数据表缺失,请检查或重新爬取该个股数据:{}'.format(s_stockcode))
        else:
            continue        
    print('股票池与数据表核对完成!')
    return re

④步骤1运行函数

#运行步骤-1
def Step_1(filename,dbinfo):
    sotckcodes,re = ReadCSV(filename) #读取股票池
    if re: #检验是否继续-成功读取股票池
        tablenames,re = ReadTableName(dbinfo) #读取表名
    if re: #检验是否继续-成功获取数据库表名
        re = CheckTableName(sotckcodes,tablenames) #检查是否有表缺失
    return sotckcodes,re

2、读取目标个股历史行情数据,返回DataFrame

检验:可回测区间是否超过X+1天

3、计算个股在设定日期区间内的开盘及收盘MA5价格并与行情数据一起保存为新的数据表,命名为 “MA5_股票代码_股票名称”

收盘MA5价格:设某交易日为N,则N的收盘MA5价格=(N的收盘价+N-1的收盘价+...+N-4的收盘价)/5

开盘MA5价格:设某交易日为N,则N的开盘MA5价格=(N的开盘价+N-1的收盘价+...+N-4的收盘价)/5

传入参数:回测开始日期(包含当日)、回测结束日期(包含当日)

返回结果:创建数据表保存,字段如下图:

日期 收盘价 开盘价 最低价 收盘MA5 开盘MA5


4、读取个股“MA5_股票代码_名称”表

返回结果:股票代码,股票名称,['日期','收盘价',....]

5、遍历个股历史行情数据,找到所有策略买入点

传入参数:步骤4“MA5_股票代码表”读取结果、收盘MA5价下跌天数X的配置

返回结果:列表 ['买入点交易日','买入价']

6、根据买入点,找到对应的策略卖出点

传入参数:步骤4“MA5_股票代码_名称”表的读取结果、步骤5返回的结果(买入点列表)

返回结果:代码,名称,列表[['买入点交易日','买入价格','对应卖出点交易日','对应卖出价格'],...]

若买入之后暂未出现对应卖出点,则返回:代码,名称[...,['买入点交易日','买入价格','null','null'],..]

7、找出除权日(此处多谢一位粉丝的提醒)

除权日定义:判断标准为(N-1日收盘价)/(N日收盘价)-100%>11%,即次日跌幅超过11%

解释:以上为除权日的粗略判断,因我们爬取到的股价未进行动态除权处理,所以可能会极大地影响到结果准确性,所以本次分析中,我们将会把持仓期间出现除权日的交易进行抹除不做统计分析。

传入参数:步骤4“MA5_股票代码表”的读取结果

返回结果:代码,名称,列表['除权日期']

8、筛除含除权日的交易记录

传入参数:步骤6返回的买卖点对应列表、步骤7返回的除权日列表

若买点交易日与卖点交易日之间含有除权日,则删除该买点和对应卖点

返回结果:

代码,名称,列表[['买入点交易日','买入价格','对应卖出点交易日或null','对应卖出价格或null'],...]

9、生成交易策略表

对所有的”MA5_股票代码_名称表"进行买卖点标记,并合并为一张交易策略表,命名为tactics表

日期 股票代码 名称 开盘价 收盘价 最低价 收盘MA5 开盘MA5 操作策略
买/卖/null

以上为准备工作,接下来我们还需要创建3个表来对资金情况、持仓情况、交易日志进行记录:

account表:记录每日资金变化

position表:记录每日持仓变化

log表:记录交易日志

9、记录资金账户情况,数据保存到数据表“account”(记录每日资金账户相关数据)

数据表初始化:

日期 可用资金 总资产 持仓价值 持股数 仓位占比 年化收益率 累计收益率
开始日期 设定初始资金 0 0 0 0.00% 0.00% 0.00%

10、记录持仓情况,数据保存到数据表“position”(记录每日持仓相关数据)

数据表初始化:

日期 股票代码 名称 市值 收盘价 成本 数量 盈亏幅度 盈亏金额
每股 0.00%

市值=现价*数量

成本=(Σ买入时股票单价*买入数量) /  总数量

10、记录交易日志,数据保存到数据表“log”(记录每天的交易数据)

数据表初始化:

日期 股票代码 名称 交易行为 价格 数量 结果
日期 代码 名称 买入/卖出 每股价格 交易数量 成功/失败

数量示例:买入100股记 “100”,卖出100股记 “-100”

结果:“可用资金不足”、“当日最低价未触达挂买价”时将买入失败;“持仓不足卖出时”将卖出失败;


接下来,开始进行回测

11、遍历个股交易日数据,进行回测

读取交易策略表tactics,

读取资金账户表account,

读取持仓表position,

读取日志表log

对tactics交易策略表进行遍历,判断当日是否符合策略交易条件

是:执行买入/卖出操作,更新log(日志表)、position(持仓表)、account(资金账户表)

否:更新position(持仓表)、account(资金账户表)

12、定义执行买入/卖出操作函数

传入参数:单笔交易数(默认100股),策略(买/卖),资金可用余额

买入检验:①当日最低股价应不小于开盘MA5价格;②账户可用资金应不小于本次交易预算

卖出检验:①可用持仓数量应不小于将卖出数量

返回结果:是否买入/卖出 成功 True/False,买入/卖出总金额


接下来我们对回测结果进行数据统计及可视化展示

13、数据统计

策略总胜率:策略交易盈利次数/总交易次数

策略个股胜率:每只股票的策略交易盈利次数/总交易次数

策略平均收益率:Σ每次策略交易盈利率/总交易次数

策略个股平均收益率:每只股票的策略平均收益率

14、数据展示

策略的总收益率趋势图,年化收益率,最大回撤

15、邮件自动推送

实盘监控,出现策略买卖点后推送邮件提醒:股票名、代码、近30日趋势图、建议买入/卖出价

你可能感兴趣的:(数据分析,python,数据分析)