量化交易学习-RSI策略2

加入交易信号二 RSI的“黄金交叉”与“死亡交叉”

用Ta-Lib计算6日的RSI值和24日的RSI值

  • 当RSI6>70或者RSI6向下穿过RSI24时,为卖出信号。
  • 当RSI6<30或者RSI6向上穿过RSI24时,为买入信号。
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt

# Create a Stratey
class TestStrategy(bt.Strategy):

    params = (
        ('RSI6period', 6),
        ('RSI24period', 24),
    )
    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        print('%s, %s' % (dt.isoformat(), txt))
    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close
        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
        # 添加Ta-Lib RSI指标
        self.RSI6=bt.talib.RSI(self.data, timeperiod= self.p.RSI6period)
        self.RSI24=bt.talib.RSI(self.data, timeperiod= self.p.RSI24period)
        self.crossover = bt.ind.CrossOver(self.RSI6, self.RSI24)  # 交叉信号

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return
         # Check if an order has been completed
        # Attention: broker could reject order if not enough cash
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else: # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))
            self.bar_executed = len(self)
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')
        
        self.order = None
    def notify_trade(self, trade):
        if not trade.isclosed:
            return
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])
        
        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        if not self.position:
            if self.crossover > 0: 
                self.order = self.buy()
            elif self.RSI6[0] < 30: 
                self.order = self.buy()
        else:
            if self.crossover < 0:
                self.order=self.close()
            elif self.RSI6[0] > 80:
                self.order = self.close() 
        
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
cerebro.addstrategy(TestStrategy)
# Datas are in a subfolder of the samples. Need to find where the script is
# because it could have been called from anywhere
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, '600519-1.csv')
# Create a Data Feed
data = bt.feeds.GenericCSVData(
        dataname = datapath,
        nullvalue = 0.0,
        dtformat = ('%Y-%m-%d'),
        datetime = 0,
        open = 1,
        high = 2,
        low = 3,
        close = 4,
        volume = 5,
        openinterest = -1
        )
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Set our desired cash start
cerebro.broker.setcash(100000.0)
# 设置交易单位大小 A股100股为一手
cerebro.addsizer(bt.sizers.FixedSize, stake = 100)

# Print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Run over everything
cerebro.run()
# Print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Plot the result
cerebro.plot()

结果如下,是盈利的

Final Portfolio Value: 119192.00

在这里插入图片描述

天数差异

短期RSI对于价格的变化情况反应比较敏感,RSI取值波动较大,长期RSI值反应相对迟钝,其波动相对较小。对于交易信号一,超买和超卖现象,使用6日的RSI值和20日的RSI值之间用哪一个时间跨度得到的收益最大那。Backtrader里有Optimize功能

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt

# Create a Stratey
class TestStrategy(bt.Strategy):

    params = (
        ('RSIperiod', 6),
        ('printlog', False),
    )
    def log(self, txt, dt=None,doprint = False):
        ''' Logging function fot this strategy'''
        if self.params.printlog or doprint:
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
        
    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close
        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
        # 添加Ta-Lib RSI指标
        self.RSI=bt.talib.RSI(
                self.data, timeperiod= self.p.RSIperiod)
        # 
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return
         # Check if an order has been completed
        # Attention: broker could reject order if not enough cash
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else: # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))
            self.bar_executed = len(self)
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')
        
        self.order = None
    def notify_trade(self, trade):
        if not trade.isclosed:
            return
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])
        
        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            
            return
        # Check if we are in the market
        if not self.position:


            if self.RSI[0] < 30:
                # BUY, BUY, BUY!!! (with default parameters)
                self.log('BUY CREATE, %.2f' % self.dataclose[0])
                
                # Keep track of the created order to avoid a 2nd order
                self.order = self.buy()
        # 如果已经在场内,则可以进行卖出操作
        else:
            
            # Already in the market ... we might sell
            if self.RSI[0] > 70:
                
                # SELL, SELL, SELL!!! (with all possible default parameters)
                self.log('SELL CREATE, %.2f' % self.dataclose[0])
                
                # Keep track of the created order to avoid a 2nd order
                self.order = self.sell()
    def stop(self):
        self.log('(RSI period %2d) Ending Value %.2f' %
                 (self.p.RSIperiod, self.broker.getvalue()), doprint = True)
            
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
strats = cerebro.optstrategy(
        TestStrategy,
        RSIperiod = range(2, 10))
# Datas are in a subfolder of the samples. Need to find where the script is
# because it could have been called from anywhere
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, 'C:/Users/taohj/python-work/CopperBat-量化/600519-1.csv')
# Create a Data Feed
data = bt.feeds.GenericCSVData(
        dataname = datapath,
        nullvalue = 0.0,
        dtformat = ('%Y-%m-%d'),
        datetime = 0,
        open = 1,
        high = 2,
        low = 3,
        close = 4,
        volume = 5,
        openinterest = -1
        )
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Set our desired cash start
cerebro.broker.setcash(100000.0)
# 设置交易单位大小 A股100股为一手
cerebro.addsizer(bt.sizers.FixedSize, stake = 100)
# Run over everything
cerebro.run(maxcpus = 1)

结果如下

2015-07-01, (RSI period  2) Ending Value 107234.00
2015-07-01, (RSI period  3) Ending Value 105259.00
2015-07-01, (RSI period  4) Ending Value 105226.00
2015-07-01, (RSI period  5) Ending Value 106260.00
2015-07-01, (RSI period  6) Ending Value 104142.00
2015-07-01, (RSI period  7) Ending Value 105521.00
2015-07-01, (RSI period  8) Ending Value 102944.00
2015-07-01, (RSI period  9) Ending Value 102944.00

看来选2日的RSI值作为交易信号一的时间跨度有更高的收益。
当然超买线和超卖线,可以取值70和30,也可以取值80和20,或者90和10.
交易信号二的短线RSI和长线RSi也可以取不同的时间跨度。

希望大家多给我意见。本人没有什么编程背景,有任何问题,欢迎在本文下方留言,或者将问题发送至邮箱: [email protected]
谢谢大家!

免责声明
本内容仅作为学术参考和代码实例,仅供参考,不对投资决策提供任何建议。本人不承担任何人因使用本系列中任何策略、观点等内容造成的任何直接或间接损失。

猜你喜欢

转载自www.cnblogs.com/CopperBat/p/12733702.html
今日推荐