python實(shí)現(xiàn)馬丁策略的實(shí)例詳解
馬丁策略本來(lái)是一種賭博方法,但在投資界應(yīng)用也很廣泛,不過(guò)對(duì)于投資者來(lái)說(shuō)馬丁策略過(guò)于簡(jiǎn)單,所以本文將其改進(jìn)并使得其在震蕩市中獲利,以下說(shuō)明如何實(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。現(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)中跳過(guò),accDropday是累計(jì)跌幅的最大計(jì)算天數(shù),用來(lái)控制入場(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é)合來(lái)看):
此策略函數(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í)行的過(guò)程進(jìn)行細(xì)化的分析,有助于提升GPU的利用率和程序執(zhí)行的性能,需要的朋友可以參考下2022-01-01使用keras實(shí)現(xiàn)非線性回歸(兩種加激活函數(shù)的方式)
這篇文章主要介紹了使用keras實(shí)現(xiàn)非線性回歸(兩種加激活函數(shù)的方式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07Alpine安裝Python3依賴出現(xiàn)的問(wèn)題及解決方法
這篇文章主要介紹了Alpine安裝Python3依賴出現(xiàn)的問(wèn)題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12解決matplotlib庫(kù)show()方法不顯示圖片的問(wèn)題
今天小編就為大家分享一篇解決matplotlib庫(kù)show()方法不顯示圖片的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05