python实现马丁策略的实例详解


Posted in Python onJanuary 15, 2021

马丁策略本来是一种赌博方法,但在投资界应用也很广泛,不过对于投资者来说马丁策略过于简单,所以本文将其改进并使得其在震荡市中获利,以下说明如何实现马丁策略。

策略

逢跌加仓,间隔由自己决定,每次加仓是当前仓位的一倍。
连续跌两次卖出,且卖出一半仓位。
如果爆仓则全仓卖出止损。
初始持仓设置为10%~25%,则可进行2到3次补仓。

初始化马丁策略类属性

def __init__(self,startcash, start, end):
 self.cash = startcash #初始化现金
 self.hold = 0 #初始化持仓金额
 self.holdper = self.hold /startcash #初始化仓位
 self.log = [] #初始化日志
 self.cost = 0 #成本价 
 self.stock_num = 0 #股票数量
 self.starttime = start #起始时间
 self.endtime = end #终止时间
 self.quantlog = [] #交易量记录
 self.earn = [] #总资产记录
 self.num_log = []
 self.droplog = [0]

为了记录每次买卖仓位的变化初始化了各种列表。

交易函数

首先导入需要的模块

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('买入价:%.2f,手数:%d,现在成本价:%.2f,现在持仓:%.2f,现在筹码:%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('卖出价:%.2f,手数:%d,现在成本价:%.2f,现在持仓:%.2f,现在筹码:%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('持有,现在仓位为:%.2f。现在成本:%.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)

持仓成本的计算方式是利用总持仓金额除以总手数,卖出时不改变持仓成本。持有则是不做任何操作只记录日志

数据接口

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

数据接口使用tushare,也可使用pro接口,到官网注册领取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

数据结构:

python实现马丁策略的实例详解

回测函数

def startback(self, data, everyChange, accDropday):
 """
 回测函数
 """
 for i in range(len(data)):
  if i < 1:
  continue
  if i < accDropday:
  drop = backtesting.accumulateVar(everyChange, i, i)
  #print('现在累计涨跌幅度为:%.2f'%(drop))
  self.martin(data[i], data[i-1], drop, everyChange,i)
  elif i < len(data)-2:
  drop = backtesting.accumulateVar(everyChange, i, accDropday)
  #print('现在累计涨跌幅度为:%.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])

因为要计算每日涨跌幅,要计算差分,所以第一天的数据不能计算在for循环中跳过,accDropday是累计跌幅的最大计算天数,用来控制入场,当累计跌幅大于某个数值且仓位为0%时可再次入场。以下是入场函数:

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('再次入场')
  self.buy(currentprice, count)
 else: self.holdstock(currentprice)

入场仓位选择0.24则可进行两次抄底,如果抄底间隔为7%可承受最大跌幅为14%。

策略函数

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('及时止损')

  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("现在累计涨跌幅为: %.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)

首先构建了droplog专门用于计算累计涨跌幅,当其大于0时重置为0,每次购买后也将其重置为0。当跌幅大于0.04则买入,一下为流程图(因为作图软件Visustin为试用版所以有水印,两个图可以结合来看):

python实现马丁策略的实例详解
python实现马丁策略的实例详解

此策略函数可以改成其他策略甚至是反马丁,因为交易函数可以通用。

作图和输出结果

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('总资产包括浮盈')
plt.show()

python实现马丁策略的实例详解

python实现马丁策略的实例详解

交易日志

到此这篇关于python实现马丁策略的实例详解的文章就介绍到这了,更多相关python马丁策略内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python网络编程学习笔记(10):webpy框架
Jun 09 Python
Python写的Socks5协议代理服务器
Aug 06 Python
使用相同的Apache实例来运行Django和Media文件
Jul 22 Python
python实现旋转和水平翻转的方法
Oct 25 Python
CentOS下Python3的安装及创建虚拟环境的方法
Nov 28 Python
Jupyter notebook设置背景主题,字体大小及自动补全代码的操作
Apr 13 Python
VScode连接远程服务器上的jupyter notebook的实现
Apr 23 Python
Python 程序报错崩溃后如何倒回到崩溃的位置(推荐)
Jun 23 Python
matplotlib 画双轴子图无法显示x轴的解决方法
Jul 27 Python
Python基于xlutils修改表格内容过程解析
Jul 28 Python
Python+Opencv身份证号码区域提取及识别实现
Aug 25 Python
python代码实现猜拳小游戏
Nov 30 Python
pycharm 多行批量缩进和反向缩进快捷键介绍
Jan 15 #Python
基于Python的接口自动化读写excel文件的方法
Jan 15 #Python
PyCharm 解决找不到新打开项目的窗口问题
Jan 15 #Python
python爬取微博评论的实例讲解
Jan 15 #Python
pycharm 复制代码出现空格的解决方式
Jan 15 #Python
pycharm 实现复制一行的快捷键
Jan 15 #Python
pycharm 快速解决python代码冲突的问题
Jan 15 #Python
You might like
全国FM电台频率大全 - 17 湖北省
2020/03/11 无线电
PHP5 面向对象程序设计
2008/02/13 PHP
php上传图片存入数据库示例分享
2014/03/11 PHP
简单谈谈php中ob_flush和flush的区别
2014/11/27 PHP
TP5框架请求响应参数实例分析
2019/10/17 PHP
jQuery自动切换/点击切换选项卡效果的小例子
2013/08/12 Javascript
JQuery设置文本框和密码框得到焦点时的样式
2013/08/30 Javascript
无限树Jquery插件zTree的常用功能特性总结
2014/09/11 Javascript
javascript中hasOwnProperty() 方法使用指南
2015/03/09 Javascript
js实现交换运动效果的方法
2015/04/10 Javascript
JavaScript中指定函数名称的相关方法
2015/06/04 Javascript
z-blog SyntaxHighlighter 长代码无法换行解决办法(基于jquery)
2015/11/18 Javascript
在JavaScript中调用Java类和接口的方法
2016/09/07 Javascript
DWR3 访问WEB元素的两种方法实例详解
2017/01/03 Javascript
jquery实现tab键进行选择后enter键触发click行为
2017/03/29 jQuery
ES6 javascript中Class类继承用法实例详解
2017/10/30 Javascript
基于jquery.page.js实现分页效果
2018/01/01 jQuery
在微信小程序里使用watch和computed的方法
2018/08/02 Javascript
详解Vue2.0组件的继承与扩展
2018/11/23 Javascript
浅谈javascript中的prototype和__proto__的理解
2019/04/07 Javascript
20个必会的JavaScript面试题(小结)
2019/07/02 Javascript
分享8个JavaScript库可更好地处理本地存储
2020/10/12 Javascript
[54:24]Optic vs TNC 2018国际邀请赛小组赛BO2 第二场
2018/08/18 DOTA
Python 文件重命名工具代码
2009/07/26 Python
Python常见异常分类与处理方法
2017/06/04 Python
Python进程间通信Queue消息队列用法分析
2019/05/22 Python
PyTorch实现更新部分网络,其他不更新
2019/12/31 Python
html5视频媒体标签video的使用方法及完整参数说明详解
2019/09/27 HTML / CSS
Booking.com亚太地区:Booking.com APAC
2020/02/07 全球购物
荷兰浴室和卫浴网上商店:Badkamerxxl.nl
2020/10/06 全球购物
中学家长会邀请函
2014/01/17 职场文书
应届生自荐信
2014/06/30 职场文书
伏羲庙导游词
2015/02/09 职场文书
不同意离婚代理词
2015/05/23 职场文书
vue如何使用模拟的json数据查看效果
2022/03/31 Vue.js
vue组件冲突之引用另一个组件出现组件不显示的问题
2022/04/13 Vue.js