量化交易从入门到放弃——体验简单策略熟悉API(生命线交易)

本文仅为学习笔记,无法保证正确性,不可作为交易参考。

策略——生命线(MA20)买卖,MA为滑动平均线,取N天均值。

1、算法逻辑

  1. 分别选取沪深300及创业板个股进行测试;
  2. 突破生命线买入1%,跌破生命线5%卖出;
  3. 按分钟回测,仓位90%以下,每分钟在股票池选取5只以市价模式开新仓;

2、代码实现(以创业板为例)

# 导入函数库
import numpy as np
import pandas as pd
from datetime import timedelta
from jqdata import *
from jqlib.technical_analysis import MA
import time

# 初始化函数,设定基准等等
def initialize(context):
    # 设定沪深300作为基准
    g.stop_profit_pct = 0.2
    g.stop_loss_pct = -0.15
    g.low_pct = 0.05
    g.code = '399006.XSHE'
    g.stock_pool_nums = 100
    g.ma_period = 20
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)

    # 过滤掉order系列API产生的比error级别低的log
    # log.set_level('order', 'error')
    
    ### 股票相关设定 ###
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
      # 开盘前运行
    run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') 
      # 开盘时运行
    # run_daily(market_open, time='open', reference_security='000300.XSHG')
      # 收盘后运行
    run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')
    
## 开盘前运行函数     
def before_market_open(context):
    # 输出运行时间
    g.stock_list = get_index_stocks(g.code)
    g.stocks_pool = [s for s in np.random.choice(g.stock_list, size=g.stock_pool_nums) if not (get_current_data()[s].paused or get_current_data()[s].is_st)]
    yesterday_price = history(1, '1d', 'close', g.stocks_pool, skip_paused=True, fq='pre').T
    # log.info(yesterday_price)
    ma20 = MA(yesterday_price.index, context.current_dt.date() - timedelta(days=1), timeperiod=g.ma_period)
    k, v = list(zip(*ma20.items()))
    ma20_df = pd.DataFrame(list(v), index=list(k), columns=['v'])
    # log.info(ma20_df)
    yesterday_price.columns = ['v']
    temp = yesterday_price.copy()
    temp = temp.merge(ma20_df, how='left', left_index=True, right_index=True).drop_duplicates()
    temp['diff'] = temp['v_x'] - temp['v_y']
    # log.info(temp)
    # temp = temp.merge(lower_ma20, how='left', left_index=True, right_index=True)
    # lower_ma20 = yesterday_price - ma20_df
    lower_ma20 = temp['diff']
    # lower_ma20.columns = 'v'
    # log.info(lower_ma20[lower_ma20 < 0].index)
    g.stocks_pool = set(lower_ma20[lower_ma20 < 0].index)
    g.per_stock_cost = context.portfolio.available_cash / g.stock_pool_nums * 5
    g.order_times_max = g.stock_pool_nums * 11
    g.order_times = 0 
    g.empty_flag = False


    
## 开盘时运行函数
# def market_open(context):


def handle_data(context, data):

    # while (context.portfolio.available_cash > 0.1 * context.portfolio.total_value) and (g.order_times <= g.order_times_max):
    for s in range(0, 5):
        if (context.portfolio.available_cash > 0.1 * context.portfolio.total_value) and (not g.empty_flag):
            # log.info('handel {}'.format(g.stocks_pool))
            try:
                s = g.stocks_pool.pop() 
            except KeyError:
                g.empty_flag = True
                break
            price = data[s].close
            ma20_today = MA(s, context.current_dt.date(), timeperiod=g.ma_period).get(s)
            log.info('s:{},p:{},ma:{}'.format(s, price, ma20_today))
            if price > 1.01 * ma20_today:
                order_target_value(s, g.per_stock_cost, MarketOrderStyle())
            else:
                g.stocks_pool.add(s)
    for s in [s for s in context.portfolio.positions.keys() if (not get_current_data()[s].paused) and (data[s].close < 0.95 * MA(s, context.current_dt.date(), timeperiod=g.ma_period).get(s))]:
        order_target(s, 0, MarketOrderStyle())
        # time.sleep(60)
    
 
# ## 收盘后运行函数  
def after_market_close(context):
    orders = get_open_orders()
    for o in orders.values():
        cancel_order(o)    
#     log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time())))
#     #得到当天所有成交记录
#     trades = get_trades()
#     for _trade in trades.values():
#         log.info('成交记录:'+str(_trade))
#     log.info('一天结束')
#     log.info('##############################################################')

3、回测结果

回测结果(沪深300个股)
回测结果(创业板个股)

4、总结

  1. handle_data按分钟回测时,每分钟执行1次,注意循环特别是while语句的使用;
  2. jqlib.technical_analysis包含常见指标;
  3. 在开盘前调用history不能取到今天的数据
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yzpwslc

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值