Python量化交易学习笔记(51)——程序化交易2

本文记录使用easytrader+easyquotation实现策略的程序化交易的流程。笔记(50)已经记录了使用easytrader进行程序化交易的过程,本文主要对easyquotation获取实时数据实现策略进行介绍。

  • easyquotation安装
pip install easyquotation
  • 选择行情数据源
import easyquotation as eq
# 选择数据源
q = eq.use('qq')     # 新浪 ['sina'] 腾讯 ['tencent', 'qq'] 
  • 获取行情数据
quotation.stocks(['sz000001', 'sh600000'], prefix=True)     # prefix默认为False

返回字典类型数据,类似于:

 {
    
    'sh000159': {
    
    'name': '国际实业', # 股票名
  'buy': 8.87, # 竞买价
  'sell': 8.88, # 竞卖价
  'now': 8.88, # 现价
  'open': 8.99, # 开盘价
  'close': 8.96, # 昨日收盘价
  'high': 9.15, # 今日最高价
  'low': 8.83, # 今日最低价
  'turnover': 22545048, # 交易股数
  'volume': 202704887.74# 交易金额
  'ask1': 8.88, # 卖一价
  'ask1_volume': 111900, # 卖一量
  'ask2': 8.89,
  'ask2_volume': 54700,
  'bid1': 8.87, # 买一价
  'bid1_volume': 21800, # 买一量
  ...
  'bid2': 8.86, 
  'bid2_volume': 78400,
  'date': '2016-02-19',
  'time': '14:30:00',
  ...},
  ......
}

以上就是easyquotation的基本用法,下面逐步记录使用easytrader+easyquotation逐步实现策略程序化交易的过程,所使用的策略为:放量突破20日均线就买入。

  1. 登录交易软件
if g_trade:
    # 登陆交易软件
    user = easytrader.use('htzq_client')
    user.prepare(user='498XXXXXXX', password='XXXXXX', comm_password='XXXXXX',
                 exe_path='C:\\e海通财独立交易\\AlternateTradeSys5.18.73\\xiadan.exe')

详细的配置可以参见笔记(50)

这里引入了一个全局变量g_trade,用于控制是否实盘交易,还是只是做数据跟踪。

  1. 获取待交易股票池
# 读取待跟踪股票代码
file = proj_path + 'data/temp/2021-03-29-20-27-59.csv'
stocks = pd.read_csv(file, converters={
    
    'code': str})['code'].tolist()

读取的csv文件中包含了前一日筛选出的收盘在20日均线以下的股票代码(不包含前缀),将所有股票代码保存在列表stocks中。

  1. 读取股票历史数据
# 读取历史数据
history_data = {
    
    }
for stock in stocks:
    if '6' == stock[0:1]:
        prefix_stock = 'sh.' + stock
    else:
        prefix_stock = 'sz.' + stock
    history_file = proj_path + 'data/extend/d/qfq/lite/' + prefix_stock + '.csv'
    history_data[stock] = pd.read_csv(history_file)[['close', 'ma_19', 'volume']].iloc[-1]

其中的条件分支主要用于在股票代码上添加前缀,来正确读取因子文件数据。baostock默认下载股票数据的代码格式"sh.XXXXXX"或"sz.XXXXXX"。因子计算可以参见笔记(47)。这里读取了股票池中股票的前一日收盘价、19日均线、前一日成交量数据。如果要使用复杂的策略,则需要提前进行对应的因子计算,并读入更多的因子。

  1. 循环遍历股票最新数据
# 循环遍历股票最新数据,判断是否买入
while True:
    time.sleep(5 * 60)

每5分钟刷新一次数据。

  1. 判断是否进入交易时间
# 判断是否进入交易时间
time_now = datetime.datetime.now()
if time_now.time() < datetime.time(9, 30, 0) \
        or datetime.time(11, 30, 0) <= time_now.time() <= datetime.time(13, 0, 0):
    continue
if time_now.time() >= datetime.time(15, 0, 0):
    break

如果是未开盘或者是午盘休息,则继续循环等待;如果收盘,则跳出循环。

  1. 更新成交量的权重
# 根据时间更新成交量权重
volume_weight = 1
if time_now.time() > datetime.time(13, 0, 0):
    delta_seconds = (time_now - datetime.datetime(time_now.year, time_now.month, time_now.day, 13, 0, 0)).total_seconds()
    volume_weight = 1 + delta_seconds / 7200

这里主要是对策略成交量的约束。如果上午突破20日均线,则要求当前成交量大于前一日成交量。如果下午突破20日均线,则按照收盘成交量是前一日两倍的标准,计算分时成交量权重。

  1. 判断是否买入
buy_stocks = {
    
    }
data = q.stocks(stocks)

if g_trade:
    balance = user.balance['可用金额']

for key in data:
    # 价格过20日均线
    ma_20 = (history_data[key]['ma_19'] * 19 + data[key]['now']) / 20
    if not data[key]['now'] >= ma_20:
        continue
    # 涨幅不能过大
    if not (data[key]['now'] - data[key]['close']) / data[key]['close'] < 0.0618:
        continue
    # 成交量
    if not data[key]['volume'] > history_data[key]['volume'] * volume_weight:
        continue

使用easyquotation获取股票实时数据,当同时满足价格突破20日均线,涨幅不能过大,且成交量满足放大条件时,进行买入。

8、买入

buy_price = 0.02 + data[key]['now']
if g_trade:
    buy_limit = min(balance, 3000)
    if 100 * buy_price < balance:
        ret = user.buy(key, buy_price, buy_limit // (buy_price * 100) * 100)
        print(ret)

buy_stocks[key] = buy_price
stocks.remove(key)
print(key)

在股票当前价格的基础上加2分作为买入价格,买入总额不超过3000元,记录价格,并在候选股票池中移除已挂买单的股票。

9、 保存符合买入条件的股票信息

if len(buy_stocks):
    pd.DataFrame.from_dict(buy_stocks, orient='index').to_csv(proj_path + 'data/temp/' + time_str + '.csv')

保存的文件名为当前时间,文件内容有两列,第一列为当前时间买入的股票代码,第二列为买入价格。以2021年3月30日下午为例,共有3只股票在3个时间点符合了买入条件,因此保存为3个文件:
在这里插入图片描述
3只股票的代码和买入价格分别为"600133:5.99"、“600338:10.62”、“000911:9.21”。到本文发布时间(2021年4月10日),2只盈利,1只亏损。

策略程序化交易代码:

import easytrader
import easyquotation as eq
import os
import sys
import pandas as pd
import time
import datetime

# 获取当前目录
proj_path = os.path.dirname(os.path.abspath(sys.argv[0])) + '/../'

g_trade = False

if __name__ == '__main__':
    if g_trade:
        # 登陆交易软件
        user = easytrader.use('htzq_client')
        user.prepare(user='498XXXXXXX', password='XXXXXX', comm_password='XXXXXX',
                 exe_path='C:\\e海通财独立交易\\AlternateTradeSys5.18.73\\xiadan.exe')

    # 读取待跟踪股票代码
    file = proj_path + 'data/temp/2021-03-29-20-27-59.csv'
    stocks = pd.read_csv(file, converters={
    
    'code': str})['code'].tolist()
    stocks.reverse()

    # 读取历史数据
    history_data = {
    
    }
    for stock in stocks:
        if '6' == stock[0:1]:
            prefix_stock = 'sh.' + stock
        else:
            prefix_stock = 'sz.' + stock
        history_file = proj_path + 'data/extend/d/qfq/lite/' + prefix_stock + '.csv'
        history_data[stock] = pd.read_csv(history_file)[['close', 'ma_19', 'volume']].iloc[-1]

    # 选择数据源
    q = eq.use('qq')
    # 循环遍历股票最新数据,判断是否买入
    while True:
        time.sleep(5 * 60)

        # 判断是否进入交易时间
        time_now = datetime.datetime.now()
        if time_now.time() < datetime.time(9, 30, 0) \
                or datetime.time(11, 30, 0) <= time_now.time() <= datetime.time(13, 0, 0):
            continue
        if time_now.time() >= datetime.time(15, 0, 0):
            break

        # 根据时间更新成交量权重
        volume_weight = 1
        if time_now.time() > datetime.time(13, 0, 0):
            delta_seconds = (time_now - datetime.datetime(time_now.year, time_now.month, time_now.day, 13, 0, 0)).total_seconds()
            volume_weight = 1 + delta_seconds / 7200

        print('\n', time_now)
        time_str = time_now.strftime('%Y-%m-%d-%H-%M-%S')
        buy_stocks = {
    
    }
        data = q.stocks(stocks)

        if g_trade:
            balance = user.balance['可用金额']

        for key in data:
            # 价格过20日均线
            ma_20 = (history_data[key]['ma_19'] * 19 + data[key]['now']) / 20
            if not data[key]['now'] >= ma_20:
                continue
            # 涨幅不能过大
            if not (data[key]['now'] - data[key]['close']) / data[key]['close'] < 0.0618:
                continue
            # 成交量
            if not data[key]['volume'] > history_data[key]['volume'] * volume_weight:
                continue

            buy_price = 0.02 + data[key]['now']
            if g_trade:
                buy_limit = min(balance, 3000)
                if 100 * buy_price < balance:
                    ret = user.buy(key, buy_price, buy_limit // (buy_price * 100) * 100)
                    print(ret)

            buy_stocks[key] = buy_price
            stocks.remove(key)
            print(key)

        if len(buy_stocks):
            pd.DataFrame.from_dict(buy_stocks, orient='index').to_csv(proj_path + 'data/temp/' + time_str + '.csv')

欢迎大家关注、点赞、转发、留言,感谢支持!
微信群用于学习交流,感兴趣的读者请扫码加微信!
QQ群(676186743)用于资料共享,欢迎加入!

在这里插入图片描述
在这里插入图片描述

おすすめ

転載: blog.csdn.net/m0_46603114/article/details/115560918