【Quant(15)】 Momentum trade

use volume indicator to backtesting , using 2618

photo by Leio McLaren on Unsplash

Highlights

  • Difficulty:★★☆☆☆
  • Backtesting by trading volume indicator and relative performance of this strategy
  • Advice: This article adopts TEJ database to calculate RSI indicators, create signals and form the return. Before reading this, 【Quant(2)】Technical Analysis is recommended to explore to better understand the basic procedure of backtesting.

Preface

Nowadays Momentum trade are frequently used to trade strategy,we often talk about the price-volume relationship .So in this article we are going to talk about this strategy which based on abnormal growing of the trading volume.but this strategy doesn't have the clear definition.so we write the function more flexible.you can change the parameter by yourself ! Following is the way to our set the parameter :

1. buy-signal : when the trading volume is 2.5 times more than the average of previous 4 days.

2. sell-singal : when the trading volume is 0.75 times less than the average of last 4 days.

The Editing Environment and Modules Required

Window10 Spyder(anaconda31)

##########
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
#################TEJ
import tejapi
tejapi.ApiConfig.api_key = 'Your Key'
tejapi.ApiConfig.ignoretz = True

Database

Security Transaction Data Table:Listed securities with unadjusted price and index. Code is ‘TWN/EWPRCD’.

Data Selection

coid="2618" #### you can replace the stock id what you want
start="2018-01-01" ### time~
end= "2022-03-2" ### end
opts={'columns': ['coid', 'mdate', 'volume', 'close_adj','close_d','open_d']} ###
#############
fly=tejapi.get('TWN/EWPRCD',coid=coid,
mdate={'gt':start,'lt':end},
paginate=True,
chinese_column_name=True,
opts=opts )

we using the popular groups in recent days to demonstrate our code .Time we select is 2018/1/1~ 2022~3/2.After we get the data ,we want to plot the data.

fly.set_index("日期",drop=True,inplace=True) # set index
plt.figure(facecolor='white',figsize=(12,8))
plt.plot(fly['收盤價'], label='收盤價')
plt.title("飛機起飛表",fontsize=25)
plt.xticks(rotation=45)
plt.xlabel('日期',fontsize=25)
plt.ylabel('股價',fontsize=25)
plt.grid()
plt.show()

Data Processing

Step 1. set the indicator

def voltrade(df,p,q,r):
df =df.copy()
df["當日交易量"]=df["成交量(千股)"].rolling(p).mean()
df["前五日總量"]=df["成交量(千股)"].rolling(q).sum()
df[str(r)+"日均線"]=df["收盤價-除權息"].rolling(r).mean()
####扣除掉當日之平均
df["前幾日平均"]=(df["前五日總量"]-df["當日交易量"])/(q-p)

return df

This function we can get previous 4(q) days average tradeing volume ,and the 5(r)ma ( we can change the q r)

r=5
stock=voltrade(fly, 1, 5, r) # the parameter is which we set in this article
stock

Step 2 find the buy singal and sell singal

def buysell(company,a,b):
company =company.copy()
buy=[]
sell=[]
hold=0
for i in range(len(company)):

if company["當日交易量"][i] > company["前幾日平均"][i]*a :
sell.append(np.nan)
if hold !=1:
buy.append(company["收盤價-除權息"][i])

hold = 1
else:
buy.append(np.nan)
elif company["當日交易量"][i]<company["前幾日平均"][i]*b :
buy.append(np.nan)
if hold !=0:
sell.append(company["收盤價-除權息"][i])
hold = 0
else:
sell.append(np.nan)
else:
buy.append(np.nan)
sell.append(np.nan)
a=(buy,sell)

company['Buy_Signal_Price']=a[0]
company['Sell_Signal_Price']=a[1]
company["買賣股數1"]=company['Buy_Signal_Price'].apply(lambda x : 1000 if x >0 else 0)
company["買賣股數2"]=company['Sell_Signal_Price'].apply(lambda x : -1000 if x >0 else 0 )
company["買賣股數"]=company["買賣股數1"]+ company["買賣股數2"]

return company
vol=buysell(stock,2.5,0.75)
plot(vol)

In this stargey ,we have done too much buying and selling which incrase frictional cost.and found that we often sell to early.Therefore we try to increase more restriction like the 5ma stargey,here is the following :

casue we are talking about the indicator ,so we plot it together .

pvtwo(volma) #seprate 
pvsame(volma)#combine

Calculate the return

In 【Quant(8)】Backtesting by MACD Indicator, we have discussed the details in the calculation of frictions cost and the method to calculate return with initial principal. In this article, we use function to achieve all of it.

def target_return(data, principal):
data=data.copy()
#計算成本
data['手續費'] = data['收盤價-除權息']* abs(data['買賣股數'])*0.001425
data['手續費'] = np.where((data['手續費']>0)&(data['手續費'] <20), 20, data['手續費'])
data['證交稅'] = np.where(data['買賣股數']<0, data['收盤價-除權息']* abs(data['買賣股數'])*0.003, 0)
data['摩擦成本'] = (data['手續費'] + data['證交稅']).apply(np.floor)

#計算資產價值
data['股票價值'] = data['買賣股數'].cumsum() * data['收盤價-除權息']
data['現金價值'] = principal - data['摩擦成本'] + (data['收盤價-除權息']* -data['買賣股數']).cumsum()
data['資產價值'] = data['股票價值'] + data['現金價值']

#計算報酬率
data['當日價值變動(%)'] = (data['資產價值']/data['資產價值'].shift(1) - 1)*100
data['累計報酬(%)'] = (data['資產價值']/principal - 1)*100

return data

We only consider the trading of common stock. There is no margin buy or margin sell situation, so we do not have to calculate premium. With the data containing trading shares and initial principal, we can quickly get the transaction costs and return. In this article, we set 16000 as our principal.

volreturn1 = target_return( volma, principal = 16000)##with ma
volreturn2 = target_return( vol, principal = 16000)##without ma
we add buy-and-hold strategy as our benchmarks.
  • The return of buy-and-hold
keep=vol.copy()
keep["買賣股數"]=0
keep["買賣股數"][0]=1000
keep["買賣股數"][len(keep)-1]=-1000
volreturn3 = target_return( keep, principal = 16000)

Performance comparison

Step 1. Comparison of cumulative return (See the details in source code)

Step 2. Performance table (See the details in source code)

Conclusion

We found that if we only use trading volume as the only indicator,the performace will equal to the buy&hold,but when we add the ma,we found that the performace is 2 times than the others ,and the sharp ratio is the highest.But this method also has obvious disadvantages .when we look at the 2018 ~2020 ,in this time period is negative pay.Perhaps the entry conditions can be set more strictly to reduce redundant buying and selling.

There are two special cases to remind the use of this method:

  1. This method cannot be used in the face of disposal of stocks, because the trading volume is bound to decline when disposed.
  2. When performing index adjustment, such as FTSE index, msci, etc., the trading volume is easy to enlarge, resulting in wrong judgment of buying and selling points.

In 2021 , “2618” started to growth ,this stargey can find the good position to buy ,and can efficient use your funds ! So we will introduce how to use TEJ -API to find the abnormal increase volume next ,and we can Cooperate with this article.

After all, the application of technical indicator varies from person to person. As a result, if readers are interested in diverse trading backtesting, welcome to purchase the plan offered in TEJ E-Shop. Construct trading strategies fitting you with high quality database.

Source Code

Extended Reading

Related Link

You could give us encouragement by …
We will share financial database applications every week.
If you think today’s article is good, you can click on the
applause icononce.
If you think it is awesome, you can hold the
applause icon until 50 times.
If you have any feedback, please feel free to leave a comment below.

--

--

TEJ 台灣經濟新報
TEJ-API Financial Data Analysis

TEJ 為台灣本土第一大財經資訊公司,成立於 1990 年,提供金融市場基本分析所需資訊,以及信用風險、法遵科技、資產評價、量化分析及 ESG 等解決方案及顧問服務。鑒於財務金融領域日趨多元與複雜,TEJ 結合實務與學術界的精英人才,致力於開發機器學習、人工智慧 AI 及自然語言處理 NLP 等新技術,持續提供創新服務