如何在Python中快速实现自己的交易策略

发布于: 修改于:雪球转发:0回复:0喜欢:0

交易者根据对市场的观察,会不时有新的交易想法需要进行验证。而程序交易的优势之一就在于能无需投入真实资金就可以快速的验证自己的交易想法,避免了无畏的损失。今天的文章将讨论如何在Python中快速的验证自己的交易想法。本文将演示在Python中构建交易策略的一个简单框架,具体包括:

数据准备

指标计算

交易信号处理

策略实现方法

数据准备

交易数据的获取方法很多,这里我们以本地导出通达信的交易数据为示例来进行演示。首先在通达信软件选择后复权的方式导出交易数据,选择后复权的原因在于如果使用前复权那么可能会存在前期股价为负数的现象,这将使得回测结果不准确。使用后复权虽然避免了这一问题,但是也同样存在价格不准确问题,更好的方法应该是使用动态复权因子。不过这里为了简单,我们不考虑该问题。首先读入已经导出的股票数据:

src_dir='F:/tdx_data/data/sh/'
df=pd.read_csv(src_dir+'SH#600036.txt',sep='\t',parse_dates=True,skiprows=1,skipfooter=1,encoding='gbk',engine='python')
df.columns=['date','open','high','low','close','volume','amount']
df['date']=pd.to_datetime(df["date"])
df.set_index('date',inplace=True)
df.head()

数据显示如下图所示,后续我们选取2020年后的数据来进行交易策略的回测。

计算指标

有了股票的交易数据后接下来就是技术指标的计算了,这里以布林线指标为例进行说明。布林指标实际就是移动平均线加/减2个标准差。因此首先使用前面Python金融数据分析系列1中计算简单移动平均的方法写一个sma函数来进行简单移动平均的计算,代码如下:

df['sma_20'] = sma(df['close'], 20)
df.tail()

现在我们已经有了20日均线数据,接下来再加上一个上轨和下轨,同样的写一个函数bb来完成布林上下轨计算,代码如下:

df['upper_bb'], df['lower_bb'] = bb(df['close'], df['sma_20'], 20)
df.tail()

通过上述代码我们得到的数据如下图所示:

进一步将该数据可视化如下所示:

交易信号

完成了数据准备,技术指标的计算,下一步就是根据交易规则产生交易信号。本例中的交易规则很简单:

股价下穿布林下轨后买入

股价上穿布林上轨后卖出

基于该规则,编写布林轨道交易函数bb_strategy如下:

def bb_strategy(data, lower_bb, upper_bb):
    buy_price = []
    sell_price = []
    bb_signal = []
    signal = 0
    
    for i in range(len(data)):
        if data[i-1] > lower_bb[i-1] and data[i] < lower_bb[i]:
            if signal != 1:
                buy_price.append(data[i])
                sell_price.append(np.nan)
                signal = 1
                bb_signal.append(signal)
            else:
                buy_price.append(np.nan)
                sell_price.append(np.nan)
                bb_signal.append(0)
        elif data[i-1] < upper_bb[i-1] and data[i] > upper_bb[i]:
            if signal != -1:
                buy_price.append(np.nan)
                sell_price.append(data[i])
                signal = -1
                bb_signal.append(signal)
            else:
                buy_price.append(np.nan)
                sell_price.append(np.nan)
                bb_signal.append(0)
        else:
            buy_price.append(np.nan)
            sell_price.append(np.nan)
            bb_signal.append(0)
            
    return buy_price, sell_price, bb_signal

buy_price, sell_price, bb_signal = bb_strategy(df['close'], df['lower_bb'], df['upper_bb'])

这段代码虽然有点多,但是基本思路却非常简单,如果股价下穿布林下轨后由于需要买入,因此代码需要将买入价格记录下来(buy_price),同时将signal标记为1,反之则记录卖出价格sell_price,同时将signal标记为-1。之后将以上信息分别记录到3个列表buy_price,sell_price,bb_signal中。具体买入,卖出信号可视化如下图所示:

交易策略

有了交易信号之后,下一步就是根据交易信号记录当前的仓位信息,具体代码如下:

position = []
for i in range(len(bb_signal)):
    if bb_signal[i] > 1:
        position.append(0)
    else:
        position.append(1)
        
for i in range(len(df['close'])):
    if bb_signal[i] == 1:
        position[i] = 1
    elif bb_signal[i] == -1:
        position[i] = 0
    else:
        position[i] = position[i-1]
        
upper_bb = df['upper_bb']
lower_bb = df['lower_bb']
close_price = df['close']
bb_signal = pd.DataFrame(bb_signal).rename(columns = {0:'bb_signal'}).set_index(df.index)
position = pd.DataFrame(position).rename(columns = {0:'bb_position'}).set_index(df.index)

frames = [close_price, upper_bb, lower_bb, bb_signal, position]
strategy = pd.concat(frames, join = 'inner', axis = 1)
strategy = strategy.reset_index().drop('date', axis = 1)

上述代码仓位信息记录在了position这一列表中,之后将仓位,信号等数据都合并保存在strategy这个DataFrame。有了上述信息,我们就可以开始计算策略收益,具体代码如下:

df_ret = pd.DataFrame(np.diff(df['close'])).rename(columns = {0:'returns'})
bb_strategy_ret = []

for i in range(len(df_ret)):
    try:
        returns = df_ret['returns'][i]*strategy['bb_position'][i]
        bb_strategy_ret.append(returns)
    except:
        pass
    
bb_strategy_ret_df = pd.DataFrame(bb_strategy_ret).rename(columns = {0:'bb_returns'})

investment_value = 100000
number_of_stocks = math.floor(investment_value/df['close'][-1])
bb_investment_ret = []

for i in range(len(bb_strategy_ret_df['bb_returns'])):
    returns = number_of_stocks*bb_strategy_ret_df['bb_returns'][i]
    bb_investment_ret.append(returns)

bb_investment_ret_df = pd.DataFrame(bb_investment_ret).rename(columns = {0:'investment_returns'})
total_investment_ret = round(sum(bb_investment_ret_df['investment_returns']), 2)
profit_percentage = math.floor((total_investment_ret/investment_value)*100)
print(cl('策略收益: {}'.format(total_investment_ret), attrs = ['bold']))
print(cl('策略收益率:{}%'.format(profit_percentage), attrs = ['bold']))

其中代码math.floor(investment_value/df['close'][-1])完成了买入数量计算,当然这里没有按照100股来进行计算,如果需要你只需要简单的取整就可以了。具体的收益计算主要由这一段代码完成:

for i in range(len(bb_strategy_ret_df['bb_returns'])):
    returns = number_of_stocks*bb_strategy_ret_df['bb_returns'][i]
    bb_investment_ret.append(returns)

总结

利用以上代码作为框架你就可以快速完成各种交易想法的验证,基于多个指标的交易策略无非就是多几次计算而已。