python實(shí)現(xiàn)馬丁策略的實(shí)例詳解
馬丁策略本來是一種賭博方法,但在投資界應(yīng)用也很廣泛,不過對(duì)于投資者來說馬丁策略過于簡(jiǎn)單,所以本文將其改進(jìn)并使得其在震蕩市中獲利,以下說明如何實(shí)現(xiàn)馬丁策略。
策略
逢跌加倉(cāng),間隔由自己決定,每次加倉(cāng)是當(dāng)前倉(cāng)位的一倍。
連續(xù)跌兩次賣出,且賣出一半倉(cāng)位。
如果爆倉(cāng)則全倉(cāng)賣出止損。
初始持倉(cāng)設(shè)置為10%~25%,則可進(jìn)行2到3次補(bǔ)倉(cāng)。
初始化馬丁策略類屬性
def __init__(self,startcash, start, end): self.cash = startcash #初始化現(xiàn)金 self.hold = 0 #初始化持倉(cāng)金額 self.holdper = self.hold /startcash #初始化倉(cāng)位 self.log = [] #初始化日志 self.cost = 0 #成本價(jià) self.stock_num = 0 #股票數(shù)量 self.starttime = start #起始時(shí)間 self.endtime = end #終止時(shí)間 self.quantlog = [] #交易量記錄 self.earn = [] #總資產(chǎn)記錄 self.num_log = [] self.droplog = [0]
為了記錄每次買賣倉(cāng)位的變化初始化了各種列表。
交易函數(shù)
首先導(dǎo)入需要的模塊
import pandas as pd import numpy as np import tushare as ts import matplotlib.pyplot as plt
def buy(self, currentprice, count):
self.cash -= currentprice*count
self.log.append('buy')
self.hold += currentprice*count
self.holdper = self.hold / (self.cash+ self.hold)
self.stock_num += count
self.cost = self.hold / self.stock_num
self.quantlog.append(count//100)
print('買入價(jià):%.2f,手?jǐn)?shù):%d,現(xiàn)在成本價(jià):%.2f,現(xiàn)在持倉(cāng):%.2f,現(xiàn)在籌碼:%d' %(currentprice ,count//100, self.cost, self.holdper, self.stock_num//100))
self.earn.append(self.cash+ currentprice*self.stock_num)
self.num_log.append(self.stock_num)
self.droplog = [0]
def sell(self, currentprice, count):
self.cash += currentprice*count
self.stock_num -= count
self.log.append('sell')
self.hold = self.stock_num*self.cost
self.holdper = self.hold / (self.cash + self.hold)
#self.cost = self.hold / self.stock_num
print('賣出價(jià):%.2f,手?jǐn)?shù):%d,現(xiàn)在成本價(jià):%.2f,現(xiàn)在持倉(cāng):%.2f,現(xiàn)在籌碼:%d' %(currentprice ,count//100, self.cost, self.holdper, self.stock_num//100))
self.quantlog.append(count//100)
self.earn.append(self.cash+ currentprice*self.stock_num)
self.num_log.append(self.stock_num)
def holdstock(self,currentprice):
self.log.append('hold')
#print('持有,現(xiàn)在倉(cāng)位為:%.2f?,F(xiàn)在成本:%.2f' %(self.holdper,self.cost))
self.quantlog.append(0)
self.earn.append(self.cash+ currentprice*self.stock_num)
self.num_log.append(self.stock_num)
持倉(cāng)成本的計(jì)算方式是利用總持倉(cāng)金額除以總手?jǐn)?shù),賣出時(shí)不改變持倉(cāng)成本。持有則是不做任何操作只記錄日志
數(shù)據(jù)接口
def get_stock(self, code): df=ts.get_k_data(code,autype='qfq',start= self.starttime ,end= self.endtime) df.index=pd.to_datetime(df.date) df=df[['open','high','low','close','volume']] return df
數(shù)據(jù)接口使用tushare,也可使用pro接口,到官網(wǎng)注冊(cè)領(lǐng)取token。
token = '輸入你的token' pro = ts.pro_api() ts.set_token(token) def get_stock_pro(self, code): code = code + '.SH' df = pro.daily(ts_code= code, start_date = self.starttime, end_date= self.endtime) return df
數(shù)據(jù)結(jié)構(gòu):

回測(cè)函數(shù)
def startback(self, data, everyChange, accDropday):
"""
回測(cè)函數(shù)
"""
for i in range(len(data)):
if i < 1:
continue
if i < accDropday:
drop = backtesting.accumulateVar(everyChange, i, i)
#print('現(xiàn)在累計(jì)漲跌幅度為:%.2f'%(drop))
self.martin(data[i], data[i-1], drop, everyChange,i)
elif i < len(data)-2:
drop = backtesting.accumulateVar(everyChange, i, accDropday)
#print('現(xiàn)在累計(jì)漲跌幅度為:%.2f'%(drop))
self.martin(data[i],data[i-1], drop, everyChange,i)
else:
if self.stock_num > 0:
self.sell(data[-1],self.stock_num)
else: self.holdstock(data[i])
因?yàn)橐?jì)算每日漲跌幅,要計(jì)算差分,所以第一天的數(shù)據(jù)不能計(jì)算在for循環(huán)中跳過,accDropday是累計(jì)跌幅的最大計(jì)算天數(shù),用來控制入場(chǎng),當(dāng)累計(jì)跌幅大于某個(gè)數(shù)值且倉(cāng)位為0%時(shí)可再次入場(chǎng)。以下是入場(chǎng)函數(shù):
def enter(self, currentprice,ex_price,accuDrop):
if accuDrop < -0.01:#and ex_price > currentprice:
count = (self.cash+self.hold) *0.24 // currentprice //100 * 100
print('再次入場(chǎng)')
self.buy(currentprice, count)
else: self.holdstock(currentprice)
入場(chǎng)倉(cāng)位選擇0.24則可進(jìn)行兩次抄底,如果抄底間隔為7%可承受最大跌幅為14%。
策略函數(shù)
def martin(self, currentprice, ex_price, accuDrop,everyChange,i):
diff = (ex_price - currentprice)/ex_price
self.droplog.append(diff)
if sum(self.droplog) <= 0:
self.droplog = [0]
if self.stock_num//100 > 1:
if sum(self.droplog) >= 0.04:
if self.holdper*2 < 0.24:
count =(self.cash+self.hold) *(0.25-self.holdper) // currentprice //100 * 100
self.buy(currentprice, count)
elif self.holdper*2 < 1 and (self.hold/currentprice)//100 *100 > 0 and backtesting.computeCon(self.log) < 5:
self.buy(currentprice, (self.hold/currentprice)//100 *100)
else: self.sell(currentprice, self.stock_num//100 *100);print('及時(shí)止損')
elif (everyChange[i-2] < 0 and everyChange[i-1] <0 and self.cost < currentprice):# or (everyChange[i-1] < -0.04 and self.cost < currentprice):
if (self.stock_num > 0) and ((self.stock_num*(1/2)//100*100) > 0):
self.sell(currentprice, self.stock_num*(1/2)//100*100 )
#print("現(xiàn)在累計(jì)漲跌幅為: %.3f" %(accuDrop))
elif self.stock_num == 100: self.sell(currentprice, 100)
else: self.holdstock(currentprice)
else: self.holdstock(currentprice)
else: self.enter(currentprice,ex_price,accuDrop)
首先構(gòu)建了droplog專門用于計(jì)算累計(jì)漲跌幅,當(dāng)其大于0時(shí)重置為0,每次購(gòu)買后也將其重置為0。當(dāng)?shù)笥?.04則買入,一下為流程圖(因?yàn)樽鲌D軟件Visustin為試用版所以有水印,兩個(gè)圖可以結(jié)合來看):


此策略函數(shù)可以改成其他策略甚至是反馬丁,因?yàn)榻灰缀瘮?shù)可以通用。
作圖和輸出結(jié)果
buylog = pd.Series(broker.log)
close = data.copy()
buy = np.zeros(len(close))
sell = np.zeros(len(close))
for i in range(len(buylog)):
if buylog[i] == 'buy':
buy[i] = close[i]
elif buylog[i] == 'sell':
sell[i] = close[i]
buy = pd.Series(buy)
sell = pd.Series(sell)
buy.index = close.index
sell.index = close.index
quantlog = pd.Series(broker.quantlog)
quantlog.index = close.index
earn = pd.Series(broker.earn)
earn.index = close.index
buy = buy.loc[buy > 0]
sell = sell.loc[sell>0]
plt.plot(close)
plt.scatter(buy.index,buy,label = 'buy')
plt.scatter(sell.index,sell, label = 'sell')
plt.title('馬丁策略')
plt.legend()
#畫圖
plt.rcParams['font.sans-serif'] = ['SimHei']
fig, (ax1, ax2, ax3) = plt.subplots(3,figsize=(15,8))
ax1.plot(close)
ax1.scatter(buy.index,buy,label = 'buy',color = 'red')
ax1.scatter(sell.index,sell, label = 'sell',color = 'green')
ax1.set_ylabel('Price')
ax1.grid(True)
ax1.legend()
ax1.xaxis_date()
ax2.bar(quantlog.index, quantlog, width = 5)
ax2.set_ylabel('Volume')
ax2.xaxis_date()
ax2.grid(True)
ax3.xaxis_date()
ax3.plot(earn)
ax3.set_ylabel('總資產(chǎn)包括浮盈')
plt.show()


交易日志
到此這篇關(guān)于python實(shí)現(xiàn)馬丁策略的實(shí)例詳解的文章就介紹到這了,更多相關(guān)python馬丁策略內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
py3nvml實(shí)現(xiàn)GPU相關(guān)信息讀取的案例分析
這篇文章主要介紹了py3nvml實(shí)現(xiàn)GPU相關(guān)信息讀取,此時(shí)就可以考慮使用py3nvml這樣的工具,針對(duì)于GPU任務(wù)執(zhí)行的過程進(jìn)行細(xì)化的分析,有助于提升GPU的利用率和程序執(zhí)行的性能,需要的朋友可以參考下2022-01-01
使用keras實(shí)現(xiàn)非線性回歸(兩種加激活函數(shù)的方式)
這篇文章主要介紹了使用keras實(shí)現(xiàn)非線性回歸(兩種加激活函數(shù)的方式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07
Alpine安裝Python3依賴出現(xiàn)的問題及解決方法
這篇文章主要介紹了Alpine安裝Python3依賴出現(xiàn)的問題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
解決matplotlib庫(kù)show()方法不顯示圖片的問題
今天小編就為大家分享一篇解決matplotlib庫(kù)show()方法不顯示圖片的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-05-05

