由于筆者并無深厚的數學功底也無深厚的金融知識, 所以不會在本文中引用各種高深的投資模型或數學模型,參考書籍主要是《海龜交易法則》《以交易為生》。
交易系統
在交易之前,我們應該首先有一個交易系統用于指導我們自己交易,不一定有什么規范,但是可以作為一個交易的依據,至于這個依據可不可行,科不科學那就見仁見智了。
當然了,這里的交易系統不一定是程序,只是指你自己的交易原則或者遵守的一些技巧或者方法,你可以手動執行也可以借助編程語言,編程語言不就是一套用來使用的工具么.
這里參考海龜交易法則里面的交易體系( 這里只是參考大方向 ).
建立一個完善的交易體系,我們至少應該思考一下六個方面。
- 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勝,微薄盈利。
最后以下圖結束.
最后的最后:
關注一下再走唄^_^
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
