竟然可以用python炒股?

由于笔者并无深厚的数学功底也无深厚的金融知识, 所以不会在本文中引用各种高深的投资模型或数学模型,参考书籍主要是《海龟交易法则》《以交易为生》。

交易系统

在交易之前,我们应该首先有一个交易系统用于指导我们自己交易,不一定有什么规范,但是可以作为一个交易的依据,至于这个依据可不可行,科不科学那就见仁见智了。

当然了,这里的交易系统不一定是程序,只是指你自己的交易原则或者遵守的一些技巧或者方法,你可以手动执行也可以借助编程语言,编程语言不就是一套用来使用的工具么.

这里参考海龟交易法则里面的交易体系(这里只是参考大方向).

建立一个完善的交易体系,我们至少应该思考一下六个方面。

  • 1、市场----买卖什么
  • 2、头寸规模----买卖多少
  • 3、入市----何时买入
  • 4、止损----何时退出亏损的头寸
  • 5、止盈----何时退出盈利的头寸
  • 6、离市----何时离市

简单的示例

  • 买卖A股
  • 全仓
  • 当日涨幅超过3%买入。
  • 当持有头寸亏损超过3%,平仓
  • 当日跌幅大于3%或者三个连续阴线

分析: 这个交易策略其实只有在行情以波浪形状向上的行情时候才能获利,如果是盘整的情况下,怕是会亏的很惨。这里之所以写的这么简单粗暴是为了后面策略测试撸代码简单。

数据获取及处理

因为这里说的是用python炒股,所以应该采用程序的方式去获取数据,如果人工炒股,下载任何股票行情软件都是可以的,但是人工的执行是需要花费比较多的精力的。

而python语言中用于获取股票行情数据的库,最有名莫过于tushare了。

这里以上证乐视的股票为例吧。

python环境安装

安装Anaconda(python2版本)

下载地址:https://www.anaconda.com/download/
注:如果没安装过这个环境的经验,就百度或者谷歌一下吧,如果不是安装anaconda则需要艰难的自行解决依赖。

如果你依然在编程的世界里迷茫,可以加入我们的Python学习扣qun:784758214,看看前辈们是如何学习的。交流经验。从基础的python脚本到web开发、爬虫、django、数据挖掘等,零基础到项目实战的资料都有整理。送给每一位python的小伙伴!分享一些学习的方法和需要注意的小细节,点击加入我们的 python学习者聚集地

安装tushare

pip install tushare

参考: http://tushare.org/

获取行情数据

import pandas as pd
import tushare as ts

# 通过股票代码获取股票数据,这里没有指定开始及结束日期
df = ts.get_k_data("300104")

# 查看前十条数据
df.head()

# 查看后十条数据
df.tail()

# 将数据的index转换成date字段对应的日期
df.index = pd.to_datetime(df.date)

# 将多余的date字段删除
df.drop("date", inplace=True, axis=1)

注:关于股票数据的相关处理需要由pandas,matplotlib的知识,参考:http://pandas.pydata.org/pandas-docs/version/0.20/10min.html

计算常用指标

# 计算5,15,50日的移动平均线, MA5, MA15, MA50
days = [5, 15, 50]
for ma in days:
    column_name = "MA{}".format(ma)
    df[column_name] = pd.rolling_mean(df.close, ma)

# 计算浮动比例
df["pchange"] = df.close.pct_change()
# 计算浮动点数
df["change"] = df.close.diff()

最终处理完成后的结果如下:

df.head()
Out[13]:
             open  close   high    low    volume    code     MA5  MA15  MA50  date
2013-11-29  9.396  9.741  9.870  9.389  146587.0  300104     NaN   NaN   NaN
2013-12-02  9.298  8.768  9.344  8.768  177127.0  300104     NaN   NaN   NaN
2013-12-03  8.142  8.414  8.546  7.890  176305.0  300104     NaN   NaN   NaN
2013-12-04  8.391  8.072  8.607  8.053  120115.0  300104     NaN   NaN   NaN
2013-12-05  7.983  7.366  8.108  7.280  253764.0  300104  8.4722   NaN   NaN   

             pchange  change
date
2013-11-29       NaN     NaN
2013-12-02 -0.099887  -0.973
2013-12-03 -0.040374  -0.354
2013-12-04 -0.040647  -0.342 

可视化

走势图

所谓一图胜前言,将数据可视化可以非常直观的感受到股票的走势。
个人觉得,如果用程序炒股还是应该一切都量化的,不应该有过多的主观观点,如果过于依赖直觉或者当时心情,那么实在没必要用程序分析了。

df[["close", "MA5", "MA15", "MA50"]].plot(figsiz=(10,18))

效果如下:

k线图

import matplotplib.pyplot as plt
from matplotlib.daet import DateFormatter
from matplotlib.finance import date2num, candlestick_ohlc

def candlePlot(data, title=""):
    data["date"] = [date2num(pd.to_datetime(x)) for x in data.index]
    dataList = [tuple(x) for x in data[
        ["date", "open", "high", "low", "close"]].values]

    ax = plt.subplot()
    ax.set_title(title)
    ax.xaxis.set_major_formatter(DateFormatter("%y-%m-%d"))
    candlestick_ohlc(ax, dataList, width=0.7, colorup="r", colordown="g")
    plt.setp(plt.gca().get_xticklabels(), rotation=50,
             horizontalalignment="center")
    fig = plt.gcf()
    fig.set_size_inches(20, 15)
    plt.grid(True)

candlePlot(df)

效果如下:

注: 这里只是一个示例,说明matplotlib的强大以及小小的演示,如果遇到什么奇怪的问题就查api或者google吧。

策略测试

手动撸代码

这里用最近买过的一只股票吧,京东方A(000725)。

# 导入相关模块
import tushare as ts
import pandas as pd

# 获取数据
df = ts.get_k_data("000725")

# 处理数据
df.index = pd.to_datetime(df.date)
df.drop("date", axis=1, inplace=True)

# 计算浮动比例
df["pchange"] = df.close.pct_change()
# 计算浮动点数
df["change"] = df.close.diff()

# 查看当前数据数据前五行
             open  close   high    low      volume    code   pchange  change
date
2015-07-20  4.264  4.234  4.342  4.165  13036186.0  000725       NaN     NaN
2015-07-21  4.136  4.195  4.274  4.096   8776773.0  000725 -0.009211  -0.039
2015-07-22  4.175  4.146  4.214  4.067   9083703.0  000725 -0.011681  -0.049
2015-07-23  4.136  4.254  4.283  4.096  12792734.0  000725  0.026049   0.108
2015-07-24  4.224  4.136  4.254  4.106  13009620.0  000725 -0.027739  -0.118

# 设定回撤值
withdraw = 0.03
# 设定突破值
breakthrough = 0.03
# 设定账户资金
account = 10000
# 持有仓位手数
position = 0

def buy(bar):
    global account, position
    print("{}: buy {}".format(bar.date, bar.close))
    # 一手价格
    one = bar.close * 100
    position = account // one
    account = account - (position * one)

def sell(bar):
    global account, position
    # 一手价格
    print("{}: sell {}".format(bar.date, bar.close))
    one = bar.close * 100
    account += position * one
    position = 0

print("开始时间投资时间: ", df.iloc[0].date)
for date in df.index:
    bar = df.loc[date]
    if bar.pchange and bar.pchange > breakthrough and position == 0:
        buy(bar)
    elif bar.pchange and bar.pchange < withdraw and position > 0:
        sell(bar)

print("最终可有现金: ", account)
print("最终持有市值: ", position * df.iloc[-1].close * 100)

输出如下:

开始时间投资时间:  2015-07-20
2015-07-29: buy 3.83
2015-07-30: sell 3.653
2015-08-04: buy 3.752
......
2018-02-27: sell 5.71
2018-03-06: buy 5.79
最终可有现金:  333.3
最终持有市值:  7527.0

结论: 通过上面的测试发现资亏了两千多...

借助测试框架

借助测试框架才是正确的回撤姿势,因为框架包含了更多的功能。这里使用pyalgotrade。

简单使用

from pyalgotrade import strategy
from pyalgotrade import technical
from pyalgotrade.barfeed import yahoofeed

# 自定义事件窗口类
class DiffEventWindow(technical.EventWindow):
    def __init__(self, period):
        assert(period > 0)
        super(DiffEventWindow, self).__init__(period)
        self.__value = None

    def onNewValue(self, dateTime, value):
        super(DiffEventWindow, self).onNewValue(dateTime, value)
        if self.windowFull():
            lastValue = self.getValues()[0]
            nowValue = self.getValues()[1]
            self.__value = (nowValue - lastValue) / lastValue

    def getValue(self):
        return self.__value

# 自定义指标
class Diff(technical.EventBasedFilter):
    def __init__(self, dataSeries, period, maxLen=None):
        super(Diff, self).__init__(dataSeries, DiffEventWindow(period), maxLen)

# 定义自己的策略
class MyStrategy(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, diffPeriod=2):
        # 传入feed及初始账户资金
        super(MyStrategy, self).__init__(feed, 10000)
        self.__instrument = instrument
        self.__position = None
        self.setUseAdjustedValues(True)
        self.__prices = feed[instrument].getPriceDataSeries()
        self.__diff = Diff(self.__prices, diffPeriod)
        self.__break = 0.03
        self.__withdown = -0.03

    def getDiff(self):
        return self.__diff

    def onEnterCanceled(self, position):
        self.__position = None

    def onEnterOk(self, position):
        execInfo = position.getEntryOrder().getExecutionInfo()
        self.info("BUY at $%.2f" % (execInfo.getPrice()))

    def onExitOk(self, position):
        execInfo = position.getExitOrder().getExecutionInfo()
        self.info("SELL at $%.2f" % (execInfo.getPrice()))
        self.__position = None

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        self.__position.exitMarket()

    def onBars(self, bars):
        account = self.getBroker().getCash()
        bar = bars[self.__instrument]
        if self.__position is None:
            one = bar.getPrice() * 100
            oneUnit = account // one
            if oneUnit > 0 and self.__diff[-1] > self.__break:
                self.__position = self.enterLong(self.__instrument, oneUnit * 100, True)
        elif self.__diff[-1] < self.__withdown and not self.__position.exitActive():
            self.__position.exitMarket()

def runStrategy():
    # 下载数据
    jdf = ts.get_k_data("000725")

    # 新建Adj Close字段
    jdf["Adj Close"] =jdf.close

    # 将tushare下的数据的字段保存为pyalgotrade所要求的数据格式
    jdf.columns = ["Date", "Open", "Close", "High", "Low", "Volume", "code", "Adj Close"]

    # 将数据保存成本地csv文件
    jdf.to_csv("jdf.csv", index=False)

    feed = yahoofeed.Feed()
    feed.addBarsFromCSV("jdf", "jdf.csv")

    myStrategy = MyStrategy(feed, "jdf")

    myStrategy.run()
    print("Final portfolio value: $%.2f" % myStrategy.getResult())

runStrategy()

输出如下

2015-07-30 00:00:00 strategy [INFO] BUY at $3.78
2015-07-31 00:00:00 strategy [INFO] SELL at $3.57
2015-08-05 00:00:00 strategy [INFO] BUY at $3.73
2015-08-06 00:00:00 strategy [INFO] SELL at $3.56
...
2018-02-13 00:00:00 strategy [INFO] BUY at $5.45
Final portfolio value: $7877.30

猛地一看会发现,用框架似乎写了更多的代码,但是框架内置了更多分析工具。
下面简单介绍。

策略可视化

from pyalgotrade import strategy
from pyalgotrade import technical
from pyalgotrade.barfeed import yahoofeed
from pyalgotrade import plotter
from pyalgotrade.stratanalyzer import returns

class DiffEventWindow(technical.EventWindow):
    def __init__(self, period):
        assert(period > 0)
        super(DiffEventWindow, self).__init__(period)
        self.__value = None

    def onNewValue(self, dateTime, value):
        super(DiffEventWindow, self).onNewValue(dateTime, value)
        if self.windowFull():
            lastValue = self.getValues()[0]
            nowValue = self.getValues()[1]
            self.__value = (nowValue - lastValue) / lastValue

    def getValue(self):
        return self.__value

class Diff(technical.EventBasedFilter):
    def __init__(self, dataSeries, period, maxLen=None):
        super(Diff, self).__init__(dataSeries, DiffEventWindow(period), maxLen)

class MyStrategy(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, diffPeriod=2):
        super(MyStrategy, self).__init__(feed, 10000)
        self.__instrument = instrument
        self.__position = None
        self.setUseAdjustedValues(True)
        self.__prices = feed[instrument].getPriceDataSeries()
        self.__diff = Diff(self.__prices, diffPeriod)
        self.__break = 0.03
        self.__withdown = -0.03

    def getDiff(self):
        return self.__diff

    def onEnterCanceled(self, position):
        self.__position = None

    def onEnterOk(self, position):
        execInfo = position.getEntryOrder().getExecutionInfo()
        self.info("BUY at $%.2f" % (execInfo.getPrice()))

    def onExitOk(self, position):
        execInfo = position.getExitOrder().getExecutionInfo()
        self.info("SELL at $%.2f" % (execInfo.getPrice()))
        self.__position = None

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        self.__position.exitMarket()

    def onBars(self, bars):
        account = self.getBroker().getCash()
        bar = bars[self.__instrument]
        if self.__position is None:
            one = bar.getPrice() * 100
            oneUnit = account // one
            if oneUnit > 0 and self.__diff[-1] > self.__break:
                self.__position = self.enterLong(self.__instrument, oneUnit * 100, True)
        elif self.__diff[-1] < self.__withdown and not self.__position.exitActive():
            self.__position.exitMarket()

def runStrategy():
    # 下载数据
    jdf = ts.get_k_data("000725")

    # 新建Adj Close字段
    jdf["Adj Close"] =jdf.close

    # 将tushare下的数据的字段保存为pyalgotrade所要求的数据格式
    jdf.columns = ["Date", "Open", "Close", "High", "Low", "Volume", "code", "Adj Close"]

    # 将数据保存成本地csv文件
    jdf.to_csv("jdf.csv", index=False)

    feed = yahoofeed.Feed()
    feed.addBarsFromCSV("jdf", "jdf.csv")

    myStrategy = MyStrategy(feed, "jdf")

    returnsAnalyzer = returns.Returns()
    myStrategy.attachAnalyzer(returnsAnalyzer)
    plt = plotter.StrategyPlotter(myStrategy)
    plt.getInstrumentSubplot("jdf")
    plt.getOrCreateSubplot("returns").addDataSeries("Simple returns", returnsAnalyzer.getReturns())

    myStrategy.run()
    print("Final portfolio value: $%.2f" % myStrategy.getResult())
    plt.plot()

runStrategy()
Python资源分享qun 784758214 ,内有安装包,PDF,学习视频,这里是Python学习者的聚集地,零基础,进阶,都欢迎

图片输出如下

注: 这里的策略测试股票选择以及时间选择并不严谨,仅作功能展示,测试结果可能有很大的巧合性。

股价监控

根据这个需求写了一个股价监控的半成品,通过邮箱监控。

技巧:在微信的辅助功能里面启用QQ邮箱提醒的功能,那么股价变动的通知就会很及时了,因为微信几乎等同于短信了。

这里简单说一下各个配置项及使用方法。

default段落

breakthrough代表突破的比例,需要传入两个值,项目里面的突破比例依次是3%,5%.

withdraw代表回撤,也需要两个值,示例为3%,5%.

attention代表关注的股票列表,填入关注的股票代码,用空格隔开
注:这里暂时没有考虑关注股票的情况,所以很多的关注股票也许有性能上的问题。

mail段落

依次输入用户名及密码以及收件人的邮箱

position段落

当前持仓的股票以及其持仓成本。
如持有京东方A(000725)以5.76的股价。
000725 = 5.76
如果多个持仓就多个如上的相应的键值对。

使用方法参考该脚本的readme
https://github.com/youerning/UserPyScript/blob/master/monitor/README.md

==PS:很难过的是英文水平不好还用因为注释,以及用英文词汇做变量名,如果词不达意请见谅。==

下单

这一部分本人暂时没有让程序自动执行,因为暂时还没有打磨出来一套适合自己并相信的体系,所以依靠股价监控的通知,根据不断修正的体系在手动执行交易。

后记

由于入市不到一年,所以就不用问我走势或者收益了, 当前战绩是5局3胜,微薄盈利。

最后以下图结束.

最后的最后:

关注一下再走呗^_^

原文地址:https://blog.51cto.com/14510224/2436279

时间: 2024-10-01 04:23:23

竟然可以用python炒股?的相关文章

用python炒股

前言 由于笔者并无深厚的数学功底也无深厚的金融知识, 所以不会在本文中引用各种高深的投资模型或数学模型,参考书籍主要是<海龟交易法则><以交易为生>. 交易系统 在交易之前,我们应该首先有一个交易系统用于指导我们自己交易,不一定有什么规范,但是可以作为一个交易的依据,至于这个依据可不可行,科不科学那就见仁见智了. 当然了,这里的交易系统不一定是程序,只是指你自己的交易原则或者遵守的一些技巧或者方法,你可以手动执行也可以借助编程语言,编程语言不就是一套用来使用的工具么. 这里参考海龟

在多个平台如何安装Python

最近的一个项目,架构师米洛需要用的mqtt,服务器开发的时候,竟然用的python脚本.运行python就需要安装开发环境,好吧,百度一下就知道了大神廖雪峰.以下部分测试通过,转载记录如下. 因为Python是跨平台的,它可以运行在Windows.Mac和各种Linux/Unix系统上.在Windows上写Python程序,放到Linux上也是能够运行的. 要开始学习Python编程,首先就得把Python安装到你的电脑里.安装后,你会得到Python解释器(就是负责运行Python程序的),一

Python,是什么让我遇见你

有些不可思议,作为一个曾学了半年C语言还挂了的计算机学渣,我竟然选择了Python这门计算机语言课.事实上,我是有过犹豫的,毕竟知道自己不擅长这方面的学习还选这门课,这种行为确实看起来有点傻傻的.但最终我还是make up my mind,就是这么神奇.    这大概和性格有关吧,我想每个人心中大概都有一种叫做倔强不服输的因子存在,有些人弱些,所以常常知难而退,做最明智的决定:有些人就强些,总爱钻牛角尖,有不撞南墙不回头的决绝.恰好我就是这么一个傻里傻气的人,至少现在是这样.C语言挂了,计算机很

Python遇到的零碎小问题

切记else语句的后面直接加冒号: 字符和数字绝对不能直接相加 对于字符与整数之间的转化 ord('E')可以将其转化为45,chr(65)可以将其转化为A 编写程序的时候尽量要考虑时间复杂度 append()的用法竟然搞错了 python中//的作用 标准库中的bisect可以进行二分法查找 self指的是自身 对于斜杠/和反斜杠\的区别总结如下: (1)浏览器地址栏网址使用斜杠 (2)windows浏览器中使用反斜杠 (3)出现在html url()属性中的路径,指定的路径是网络路径,所以必

Python/MOOC /翻Wall和互联网编程的那些事by tsy

Python MOOC 翻Wall和互联网编程的那些事by tsy 声明: 1)本报告由博客园bitpeach撰写,版权所有,免费转载,请注明出处,并请勿作商业用途. 2)若本文档内有侵权文字或图片等内容,请联系作者bitpeach删除相应部分. 3)本文档内容涉及主题在引言中提及.仅仅作为参考用途,抛砖引玉,不作为证据证明用途,请自行取舍,核实引用. 目录 0引言    1 1 Python的那些事    2 1.1Python的安装思路与简要介绍    2 1.1.1 Python安装思路 

使用python2.7炒股

参考链接 用python炒股 http://blog.51cto.com/youerning/2083764?lblinux下安装Anaconda https://www.cnblogs.com/mypath/articles/7877493.html 原文地址:http://blog.51cto.com/tangyade/2084493

python selenium系列(一):框架介绍及安装

一  selenium是什么? 引用百度百科的介绍selenium的一段话: "Selenium 是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等.这个工具的主要功能包括:测试与浏览器的兼容性--测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上.测试系统功能--创建回归测试检验软件功能和用

Python 之父再发文:构建一个 PEG 解析器

花下猫语: Python 之父在 Medium 上开了博客,现在写了两篇文章,本文是第二篇的译文.前一篇的译文 在此 ,宣布了将要用 PEG 解析器来替换当前的 pgen 解析器. 本文主要介绍了构建一个 PEG 解析器的大体思路,并介绍了一些基本的语法规则.根据 Python 之父的描述,这个 PEG 解析器还是一个很笼统的实验品,而他也预告了,将会在以后的系列文章中丰富这个解析器. 阅读这篇文章就像在读一篇教程,虽然很难看懂,但是感觉很奇妙:我们竟然可以见证 Python 之父如何考虑问题.

常见编程语言对REPL支持情况小结[转]

文章转载自http://www.nowamagic.net/librarys/veda/detail/2462 最近跟一个朋友聊起编程语言的一些特性,他有个言论让我略有所思:“不能REPL的都是渣”.当然这个观点有点偏激,但我们可以探究一下,我们常用的编程语言里面,哪些支持REPL,哪些不支持,还有REPL的一些概况. 在一般的脚本语言中,有REPL是常态,因为REPL非常的方便.编程术语 REPL(Read-Eval-Print Loop) 中文的话有翻译成“交互式解释器”或“交互式编程环境”