• 2020-11-20 17:26:05

最近刚开始学习量化交易，在聚宽网上看了几篇教程，对操作流程有了大致的了解，接下来打算好好研究一下交易策略。

据大奖章基金的Simons透露，他那个每年收益率20%以上的系统，一点都不费解(complicated)，但是非常复杂(complex)。

我的理解是，一个好的量化交易系统，不一定要用到高深的算法和技术，但是必须包含很多种简单的算法和技术。

换句话说，你得从最基础的算法开始，一个模块一个模块地加上去，选股、择时、风控、资金管理，每个方向都要综合考虑好几种不同的指标，才能打造出一个不费解但很复杂(not complicated but complex)的交易系统。

爱因斯坦说过，上帝只做加法。

也许基于人工智能(AI)的交易系统构造起来不用这么麻烦，这个以后有空再研究。

眼下先从择时技术开始，先看看最简单的MACD，也就是双均线策略。

MACD指标

MACD系列指标由三个指标沟构成，分别是DIF，DEA和HIST。DIF是12日指数移动平均线(EMA12，又称快线)与26日指数移动平均线（EMA26，又称慢线）的背离程度： $$DIF=EMA(12)−EMA(26)$$

DEA是DIF的9日指数移动平均线： $$DEA=EMA(DIF,9)$$

HIST是DIF与DEA的差值乘以2： $$HIST=(DIF−DEA)×2$$

HIST又称MACD柱，是MACD系列指标中最重要的一个，有些人只根据它来决定是否买入卖出，但我查询了一番文献，还进行了一系列的试错，发现还是综合考虑另外两个指标更好。

废话不多说了，上代码。

Python代码

第一步：导入各种库

import numpy as np

import pandas as pd

import talib as ta

# 这个是聚宽网(joinquant)的数据下载API，免费账户每天能下载100万条数据

from jqdatasdk import *

# 登录验证

auth("你的手机号", "你的密码")

import matplotlib.pyplot as plt

%matplotlib inline

第二步：下载数据

# 下载2015-2018年的沪深300指数，频率为每天，只要收盘价

price = get_price("000300.XSHG", start_date="2015-01-01", end_date="2018-12-31", frequency="daily", fields=['close'])['close']

# 用python自带的tseries库中的pct_change()函数计算日收益率

ret = price.pct_change()

# 画图

plt.figure(figsize=(18,8))

ax1 = plt.subplot(2,1,1)

ax1.plot(price)

ax2 = plt.subplot(2,1,2)

ax2.plot(ret)

plt.show()沪深300指数和日收益率

这4年间，沪深300指数的走势还是很典型的：2015年暴涨暴跌，2016-2017两年间温和上涨，2018年快速下跌。

第三步：计算指标

# 用talib库中的相应函数计算MACD指标

dif, dea, hist = ta.MACD(price)

# 计算EMA12和EMA26

ema12 = ta.EMA(price, 12)

ema26 = ta.EMA(price, 26)

第四步：生成交易信号

这里只考虑做多，不考虑做空的情况。

为了方便比较，我尝试了集中不同的策略。

# sig1只考虑HIST指标，HIST转正时开仓买入，转负时清仓

sig1 = (hist>0)

# sig2同时考虑HIST指标和DEA指标，只有当HIST转正，且DEA在0以上时，才开仓买入，任何一个指标变负即清仓。

# 这是文献中建议的方法

sig2 = (hist>0) & (dea>0)

# sig3同时考虑HIST和EMA指标，只有当HIST为正，而且当前价格在慢线（26日指数加权平均价）上方时，才开仓买入，任何一个指标转负即清仓。

# 网上有人建议过这种方法（如果我没有理解错的话）

sig3 = (hist>0) & (price>ema26)

接下来，我们来直观地比较一下这三个交易信号。

plt.figure(figsize=(18,12))

ax1=plt.subplot(4,1,1)

ax1.plot(price)

ax2=plt.subplot(4,1,2)

ax2.bar(x=sig1.index, height=sig1.values)

ax3=plt.subplot(4,1,3)

ax3.bar(x=sig2.index, height=sig2.values)

ax4=plt.subplot(4,1,4)

ax4.bar(x=sig3.index, height=sig3.values)

plt.show()交易信号

看起来策略1最激进，策略2最保守。后者完美地避开了15年和18年的两段暴跌，期间一次买入指令也没有发出过，但在16-17年的缓慢回升中，参与度似有不足。

第五步：模拟交易

简单起见，这里不考虑手续费。

以策略2为例，作图比较该策略和“买入-持有”策略的表现。

# sig2滞后一期、去除空值、转换成整数

sig2_lag = sig2.shift(1).fillna(0).astype(int)

# sig2_lag与股票日收益率相乘，即可得策略日收益率。python能自动对齐时间序列的日期。

sig2_ret = sig2_lag*ret

# 计算策略累计收益

cum_sig2_ret = (1+sig2_ret).cumprod()

# 把股票价格转换成从1开始，方便比较

price_norm = price/price[0]

# 开始作图

plt.figure(figsize=(18,8))

plt.plot(price_norm)

plt.plot(cum_sig2_ret)

plt.legend(["benchmark", "strategy cumulative return"], loc="upper left")

plt.show()累计收益率

由此可见，策略2在股市暴涨暴跌期间表现出色，它几乎完整地抓住了15年上半年的暴涨，却完美地避开了15年下半年和18年的暴跌。但是，在股市温和上涨的16、17年，该策略的表现却落后于大盘。

总而言之，该策略简单归简单，表现却不俗，在大盘下跌近20%的4年中，实现了近60%的收益，目测最大回测不超过10%。

当然，这款策略还有改进的余地，比如说，如果把交易频率调低，也许表现会更好。

接下来，我打算寻找：

1. 一个更加适应温和上涨行情的策略；

2. 一个能有效区分暴涨暴跌行情和温和涨跌行情的指标。

请大家积极发言献策！

更多相关内容
• 博文《Python量化交易策略及回测系统》详细的介绍了Python量化交易策略编写的全过程，包括： 1、数据的获取 2、量化交易策略回测系统的编写 3、量化交易策略的设计 4、使用量化交易策略及回测系统对多个股票进行回测...
• ## Python量化交易策略及回测系统

千次阅读 热门讨论 2022-03-11 20:30:37
由于本文篇幅较长，而且文中关于python数据分析的知识点、python金融量化的知识点较多，因此在文章的开头先给出本文整体思路，以便读者能够拥有较为清晰的脉络通读全文。 第一部分：模块导入，主要是将后面需要用到...

# 前言：行文思路

由于本文篇幅较长，而且文中关于python数据分析的知识点、python金融量化的知识点较多，因此在文章的开头先给出本文整体思路，以便读者能够拥有较为清晰的脉络通读全文。
第一部分：模块导入，主要是将后面需要用到的模块进行导入（简单，非重点）
第二部分：数据获取，鉴于在网络上股票数据不易找到，Wind金融终端等数据库数据收费，通过多方查找，终于让我找到了能够免费下载股票数据的模块，建议大家收藏（简单，非重点）
第三部分：将股票数据转化为新的数据类型，通过上面的方法下载下来的数据类型是我们常见的DataFrame，虽然pandas的功能已经很强大了，但是为了加入新的数据指标以及方便下一步操作，最好还是将DataFrame数据转化为一种新的数据类型（较难，非重点）
第四部分：策略编写，也就是利用代码将我们在股票市场中的交易原则表达出来（较难，重点）
第五部分：回测系统编写，股票回测即是基于历史已经发生过的真实行情数据，在历史上某一段时间内，模拟真实金融市场中股票的买入、卖出，得出这个时间段内的盈利率等数据（较难，重点）
第六部分：实例化策略并回测得到收益，继承一个策略类，得到一个实际的例子，利用股票数据回测得出结果（简单，重点）

# 1、模块导入

import akshare as ak
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from collections import namedtuple
from collections import OrderedDict
from collections.abc import Iterable
from functools import reduce
from abc import ABC, abstractmethod


akshare：用于下载股票的交易数据(前复权)
collections：对基本数据类型做进一步处理,实现特定的数据类型
abc：主要定义了基本类和最基本的抽象方法，可以为子类定义共有的接口API，不需要具体实现

# 2、数据获取

# 获取某一只股票一段时间的数据
stock_sz300750_df = ak.stock_zh_a_daily(symbol="sz300750", start_date="20200103", end_date="20211231", adjust="qfq")
# list_date = list(stock_sz300750_df['date'])
# stock_sz300750_df.index = list_date


函数ak.stock_zh_a_daily()用于获取A股股票数据

# 3、股票数据类型转换

由于后面写了两个量化交易策略，而且策略中的有部分指标不相同，所以在这一部分以及下面回测系统两部分面向对象编程，有部分函数只用于策略一，有部分只用于策略二。

# 将股票数据转化为新的数据类型
def __init__(self, price_array, date_array=None):
self.price_array = price_array
self.date_array = self._init_days(date_array)
self.change_array = self._init_change()
self.s_short = self._init_sma_short(price_array)
self.s_long = self._init_sma_long(price_array)
self.stock_dict = self._init_stock_dict()

def _init_change(self):
# 收益率

change_array = self.price_array.pct_change(periods=1)
return change_array

def _init_days(self, date_array):
# 日期序列

date_array = [str(date) for date in date_array]
return date_array

def _init_sma_short(self, price_array):
# 5日移动平均线

s_short = price_array.rolling(window=5, min_periods=5).mean()
return s_short

def _init_sma_long(self, price_array):
# 30日移动平均线

s_long = price_array.rolling(window=30, min_periods=30).mean()
return s_long

def _init_stock_dict(self):
# 将股票的日期、收盘价、涨跌幅转化为一个新的数据类型

stock_namedtuple = namedtuple('stock', ('date', 'price', 'change', 's_short', 's_long'))

# 使用以被赋值的date_array等进行OrderedDict的组装
stock_dict = OrderedDict((date, stock_namedtuple(date, price, change, s_short, s_long)) for date, price, change, s_short, s_long
in zip(self.date_array, self.price_array, self.change_array, self.s_short, self.s_long))
return stock_dict

def filter_stock(self, want_up=True, want_calc_sum=False):
# 判断交易日股票是上涨还是下跌
# Python中的三目表达式的写法
filter_func = (lambda p_day: p_day.change > 0) if want_up else (lambda p_day: p_day.change < 0)
# 使用filter_func做筛选函数
want_days = list(filter(filter_func, self.stock_dict.values()))

if not want_calc_sum:
return want_days

# 需要计算涨跌幅和
change_sum = 0.0
for day in want_days:
change_sum += day.change
return change_sum


相同指标：date、price、change
策略一：s_short、s_long分别为5日移动平均线和30日移动平均线；可以根据自己的需求更改参数数据
策略二：函数filter_stock()，用于判断交易日股票是上涨还是下跌

最后将DataFrame数据转换为自定义数据类型OrderedDict

trade_days = StockTradeDays(stock_sz300750_df['close'], stock_sz300750_df['date'])
print(day)


# 4、回测系统编写

class TradeStrategyBase(ABC, object):   # 只能被继承，不能实例化
# 交易策略抽象基类

@abstractmethod
# 买入策略基类
pass

@abstractmethod
def sell_strategy(self, *args, **kwargs):
# 卖出策略基类
pass

# 交易回测系统

"""
"""
# 交易盈亏结果序列
self.profit_array = []

# 执行交易回测

# 以时间驱动，完成交易回测

# 如果有持有股票，加入交易盈亏结果序列
self.profit_array.append(day.change)
#                 print("日期：{}，持有中".format(day.date))

# hasattr: 用来查询对象有没有实现某个方法
# 买入策略执行
#                     print("日期：{}，买入策略执行".format(day.date))

# 卖出策略执行
#                     print("日期：{}，卖出策略执行".format(day.date))


# 5、策略编写

class TradeStrategy1(TradeStrategyBase):
"""
交易策略1: 利用5日移动平均线与30日移动平均线交叉点进行股票买卖
当5日移动平均线从下往上穿过30日移动平均线时，买入股票并持有
当5日移动平均线从上往下穿过30日移动平均线时，卖出股票
"""
def __init__(self, stock_df):
self.keep_stock_day = -1

# 只有当长期移动平均线的数据有了，才能进行下一步操作

# 今日移动平均线值

# 昨日移动平均线值

if today_short > today_long and yesterday_short < yesterday_long:
# 买入条件成立：
self.keep_stock_day = 1

# 只有当长期移动平均线的数据有了，才能进行下一步操作

# 今日移动平均线值

# 昨日移动平均线值

if today_short < today_long and yesterday_short > yesterday_long:
# 卖出条件成立：
self.keep_stock_day = 0


移动平均线是将一定时期内的股票价格加以平均，把不同时间的平均值连接起来形成一根MA，利用长短期的移动平均线交叉点观察股票价格变动趋势的一种技术指标。因此，只有到了第30天才可以获得30日移动平均值，才可能进行买卖。
判断买入条件：当短期移动平均线从下往上穿过长期移动平均线时，可以认为短期内股价的趋势向上，股价可能会上涨
判断卖出条件：当短期移动平均线从上往下穿过长期移动平均线时，可以认为短期内股价的趋势向下，股价可能会下跌

class TradeStrategy2(TradeStrategyBase):
"""
交易策略2: 追涨杀跌策略，当股价连续两个交易日上涨
当股价连续两个交易日下跌
且下跌幅度超过阀值默认s_sell_change_threshold()，卖出股票
"""
def __init__(self):
self.keep_stock_day = 0
self.s_sell_change_threshold = -0.05   #下跌卖出阀值

if self.keep_stock_day == 0 and trade_ind >= 1:
"""
当没有持有股票的时候self.keep_stock_day == 0 并且
"""
# 昨天是否股价上涨
# 两天总涨幅
if today_down and yesterday_down and down_rate > self.s_buy_change_threshold:
self.keep_stock_day += 1

# 昨天是否股价下跌
# 两天总跌幅
if today_down and yesterday_down and down_rate < self.s_sell_change_threshold:
# 卖出条件成立：连跌两天，跌幅超过s_sell_change_threshold
self.keep_stock_day = 0

@property
# getter获取属性函数

# setter属性赋值
"""
上涨阀值需要为float类型
"""
# 上涨阀值只取小数点后两位

@property
def s_sell_change_threshold(self):
# getter获取属性函数
return self.__s_sell_change_threshold

@s_sell_change_threshold.setter
def s_sell_change_threshold(self, s_sell_change_threshold):
# setter属性赋值
if not isinstance(s_sell_change_threshold, float):
"""
上涨阀值需要为float类型
"""
# 上涨阀值只取小数点后两位
self.__s_sell_change_threshold = round(s_sell_change_threshold, 2)


策略二可以认为是非理性人在股票市场中交易时，遇到多日上涨且上涨幅度较大时，会认为股票有继续上涨的趋势，为了获利所以买入股票；但当某一股票连续下跌且下跌幅度超过心理预期时，会认为股票又继续下跌的趋势，为了止损卖出股票。
策略二中买入股票条件为：当股价连续两个交易日上涨且上涨幅度超过0.05，买入股票并持有
卖出条件为：当股价连续两个交易日下跌且下跌幅度超过-0.05，卖出股票
相关参数可以根据需求修改

# 6、实例化策略

# 实例化策略1
print('回测策略1总盈亏为：{}%'.format(reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100))


经过前面的所有步骤之后，就可以实例化一个交易策略，利用交易数据进行回测，可得到相应的结果：

# 实例化策略2
print('回测策略2总盈亏为：{}%'.format(reduce(lambda a, b: a + b, trade_loop_back.profit_array) * 100))


结果：

# 非面向对象的编程

由于对面向对象编程不太擅长，所以我对两个策略又分别写了新的程序，以判断上文面向对象程序是否正确

changes_list_1 = []
flag = -1
short2 = day.s_short
long2 = day.s_long
if pd.isna(long1):
continue
if flag == 1:
changes_list_1.append(day.change)
print("日期：{}，持有中".format(day.date))
if short2 > long2 and short1 < long1:
flag = 1
print("日期：{}，买入策略执行".format(day.date))
if short2 < long2 and short1 > long1:
flag = 0
print("日期：{}，卖出策略执行".format(day.date))

print('回测策略1总盈亏为：{}%'.format(reduce(lambda a, b: a + b, changes_list_1) * 100))
plt.plot(np.array(changes_list_1).cumsum())


结果：

# 策略2
changes_list_2 = []
flag = 0
today_down = day.change
if flag > 0:
changes_list_2.append(day.change)
print("日期：{}，持有中".format(day.date))
if today_down > 0 and yesterday_down > 0 and today_down + yesterday_down > 0.01:
flag += 1
print("日期：{}，买入策略执行".format(day.date))
if today_down < 0 and yesterday_down < 0 and today_down + yesterday_down < -0.01:
flag = 0
print("日期：{}，卖出策略执行".format(day.date))

print('回测策略2总盈亏为：{}%'.format(reduce(lambda a, b: a + b, changes_list_2) * 100))
plt.plot(np.array(changes_list_2).cumsum())


结果：

# 分析总结

以上策略只用于量化分析，并不适合用于实际交易，之所以有较高的盈利，得益于宁王领衔的新能源板块的强势，大家也可以试试其他的股票，比如药明康德（代码：SH603259)

可以看出策略对该股票进行回测交易时，获得的盈利并不客观，甚至出现较大的亏损，因此，需要对相关策略进行参数调整修改，或者发掘其他更为有效的策略……

最后，大家如果觉得文章写的不错的话，可以点赞、收藏、关注三连哦~文中出现的所有代码已经打包上传至我的资源了，可以下载下来研究分析和运行查看

展开全文
• 本文主要记录保护点卖出策略，给买入的股票设立保护点，随着股票收盘价的提升，保护点不断提高，股价一旦跌破保护点，即卖出股票。 示例的买入条件为，5日线金叉60日线，且股价进行小幅回踩（较金叉日收盘价下跌1%）...
• python量化交易教程，从Python入门到量化交易策略，量化交易师的python日记，股票量化交易，alpha多因子模型，宏观研究，布林带，均线系统，cci顺势指标探析，EMV技术指标的构建及应用，FPC指标选股，动量模型，基于...
• Python定量交易策略包括MACD，Pair Trading，Heikin-Ashi，London Breakout，Awesome，Dual Thrust，Parabolic SAR，Bollinger Bands，RSI，Pattern Recognition
• Additionally, please note that, all scripts are historical data backtesting/forward testing (basically via Python, not C++, maybe Julia in the near future). The assumption is that all trades are ...

Intro

We’re right 50.75 percent of the time... but we’re 100 percent right 50.75 percent of the time, you can make billions that way.

--- Robert Mercer, co-CEO of Renaissance Technologies

If you trade a lot, you only need to be right 51 percent of the time, we need a smaller edge on each trade.

--- Elwyn Berlekamp, co-Founder of Combinatorial Game Theory

The quotes above come from a book by Gregory Zuckerman, a book every quant must read, THE MAN WHO SOLVED THE MARKET.

Most scripts inside this repository are technical indicator automated trading. These scripts include various types of momentum trading, opening range breakout and statistical arbitrage strategies. Yet, quantitative trading is not only about technical analysis. It can refer to computational finance to exploit derivative price mismatch, pattern recognition on alternative datasets to generate alphas or low latency order execution in the market microstructure. Hence, there are a few ongoing projects inside this repository. These projects are mostly quantamental analysis on some strange ideas I come up with to beat the market (or so I thought). There is no HFT strategy simply because ultra high frequency data are very expensive to acquire (even consider platforms like Quantopian or Quandl). Additionally, please note that, all scripts are historical data backtesting/forward testing (basically via Python, not C++, maybe Julia in the near future). The assumption is that all trades are frictionless. No slippage, no surcharge, no illiquidity.

Data Source

Strategies:

1. MACD oscillator

MACD oscillator is trading strategy 101. MACD refers to Moving Average Convergence/Divergence. It is a momentum trading strategy which holds the belief that upward/downward momentum has more impact on short term moving average than long term moving average. It only takes 5 minutes for any bloke with no background in finance to trade with MACD signals. Regarding the simplicity of MACD oscillator, it is the most common strategy among the non-professionals in the market. In behavioral economics, the more people believe in the strategy, the more effective the strategy becomes (not always true, e.g. 2008). Therefore, we should not underestimate the power of MACD oscillator.

For the strategy itself, we compute long term moving average and short term moving average on the close price of a given stock. To generate the trading signal, we implement a comparison between the moving averages of different time horizons. When short term moving average is above long term moving average, we long the given stock accordingly. Vice versa.

Pair trading is the basic form of statistics arbitrage. It relies on the assumption that two cointegrated stocks would not drift too far away from each other. First step, we select two stocks and run Engle-Granger two step analysis. Once the criteria of cointegration is met, we standardize the residual and set one sigma away (two tailed) as the threshold. After that, we compute the current standardized residual of the selected stocks accordingly. When the standardized residual exceeds the threshold, it generates the trading signal. The simple rule is we always long the cheap stock and short the expensive stock.

The core idea of pair trading is cointegration. Metaphorically speaking, cointegration is like a couple in a clingy relationship where two parties are crazy-glued together. Yet, most relationships break sooner or later, and only the very few can make it to the marriage (from a statistics perspective, not being pessimistic). Hence, it is important to frequently check on the status quo of cointegration before any pair trading order execution (the same applies to relationships).

3. Heikin-Ashi candlestick

Heikin-Ashi, the exotic name actually referring to 'Average Bar' in Japanese, is an alternative style of candlestick chart. The sophisticated rules of Heiki-Ashi are designed to filter out the noise for momentum trading. Hence, Heikin-Ashi shows more consecutive bars in contrast to the standard candlestick, which makes price momentum and reverse points more distinguishable in figures. Arguably it should outperform the standard candlestick in sideways and choppy markets.

For the strategy itself, initially we make a few transformations on four vital benchmarks - Open, Close, High, Low. The next step is to apply unique Heikin-Ashi rules on Heikin-Ashi Open, Close, High, Low to generate trading signals. The downside of Heikin-Ashi (or any momentum trading strategies) is the slow response. Thus, we should set up the stop loss position accordingly so that we don't get caught up in any flash crash.

The rules of Heikin-Ashi can be found in Quantiacs.

4. London Breakout

To one of my favourite cities in the world! Proud to be a Londoner!

London Breakout is an intra daily opening range breakout strategy. Basically, it is a fascinating information arbitrage across different markets in different time zones. FX market runs 24/7 globally. For instance, you cannot long the stock of Ford in ASX simply because Ford is listed in NYSE. As FX market is decentralised, you can long any currency pair in any market as long as the market is open. That leaves a door to take a peek at the activity in a closed foreign FX market before the opening of domestic FX market.

Back to London Breakout, London and Tokyo are two of the largest FX markets in the world. Tokyo FX trading hour is GMT 0:00 a.m. - GMT 8:59am. London FX trading hour (no summer daylight saving) begins at GMT 8:00 a.m. Even though there is an hour of overlap, the crucial timeframe of London Breakout is GMT 7:00 a.m. - GMT 7:59 a.m. a.k.a. the last trading hour before the opening of London market. The price movement of the crucial timeframe incorporates the information of all the overnight activities of financial market (from the perspective of the current time zone).

For the strategy itself, we establish upper and lower thresholds prior to the high and low of the crucial timeframe. Once London FX market opens, we spend the first couple of minutes to check if the price would breach the preset boundaries. If it is above threshold, we long the currency pair accordingly. Vice versa. Nevertheless, we should set up a limit to prevent us from trading in the case of abnormal opening volatility. Normally, we clear our positions based on our target stop loss or stop profit respectively. By the end of the trading hour (still from the perspective of the current time zone), if there are any open positions, we clear them out.

5.Awesome oscillator

Awesome oscillator is an upgraded version of MACD oscillator. It is one of those momentum strategies focusing on the game of moving average. Instead of taking simple moving average on close price, awesome moving average is derived from the mean of high and low price. Similar to MACD oscillator, it takes both short term and long term moving averages to construct the oscillator.

There are various strategies for awesome oscillator to generate signals, such as traditional moving average divergence, twin peaks and saucer. Twin peaks is just one of the many names of bottom W pattern. The pattern recognition will be covered in another chapter so the main focus of this chapter is saucer. Saucer is slightly more complex to implement than the traditional divergence. In return, saucer has the power to beat the slow response of the traditional divergence. Generally speaking, a faster response may sound awesome, but it does not guarantee a less risky outcome or a more profitable outcome. Hence, we will take MACD oscillator as a control group, to test if awesome oscillator can actually outperform MACD oscillator.

The rules of awesome oscillator could be found in TradingView.

6.Oil Money project

This project is inspired by an article on oil-backed foreign exchange. Amid the bullish outlook for crude oil, the currency exchange of oil producing countries would also bounce back. Does this statement really hold?

According to the article by Bloomberg (or many other similar research), researchers examine the correlation between petrocurrency and oil price, instead of the causality. But correlation does not equal to causality. Correlation could be a coincidence of a math game. We simply cannot draw the conclusion that oil price moves the currency. Some researchers even use bootstrapping which greatly destroys the autocorrelation of a time series. Thus, it is vital to apply academic analysis and computer simulation on some petrocurrencies to test the causality of oil.

For more details, please refer to the read me page of a separate directory or quant trading section on my personal blog.

7.Dual Thrust

If you search dual thrust on google, you will end up with results of rocket engine. Don't panic yet, you can rest assured that dual thrust strategy is nowhere near rocket science. It is just an opening range breakout strategy developed by the founder of Universal Technical Systems. The mathematics involved in this strategy is merely primary school level.

Initially we establish upper and lower thresholds based on previous days' open, close, high and low. When the market opens and the price exceeds certain thresholds, we would take long/short positions prior to upper/lower thresholds. The strategy is quite useful in intra daily trading. However, there is no stop loss/profit position in this strategy. We reverse our positions when the price goes from one threshold to the other. We need to clear all positions by the end of the day.

Rules of dual thrust can be found in QuantConnect.

8.Parabolic SAR

Parabolic SAR is an indicator to identify stop and reverse of a trend. Usually, Parabolic SAR is presented as dotted line either above or below the price in charts. When the price is an uptrend, SAR curve would sit below the price. When the price is downtrend, SAR curve would rise above the price. Parabolic SAR is always considered as a symbol of resistance to the price momentum. When SAR curve and the price curve cross over, it is when trade orders are supposed to be executed.

The building of this strategy seems very simple, but the construction of the indicator is extremely painful due to the involvement of recursive calculation. Illustration on how to compute Parabolic SAR can be found in Wikipedia but it is not very well explained. To get a clear idea of the calculation, my personal recommendation is to take a look at the spreadsheet made by joeu2004.

It is worth mentioning that SAR and RSI (which will be featured in a later chapter) shares the same founder, Welles Wilder. The guy is a real legend who used to work as mechanical engineer and real estate developer and later became a technical analyst. His book on technical trading system is a must-read for anyone that wants to elevate quant trading system to the next level.

9.Bollinger Bands Pattern Recognition

Bollinger Bands is a very simple but powerful indicator. There are three bands of this indicator. The mid band is the moving average on the price series (usually takes 20 lags). The upper and lower bands are two moving standard deviations away from the mid band. Bollinger Bands can be used to test for various types of strategies.

For volatility trading, contraction and expansion of the band width are crucial elements. Any distinct momentum clustering (it can take form of either upward or downward) would result in a Bollinger Bands expansion. And the oscillation in a horizontal channel would result in a Bollinger Bands contraction.

For momentum trading, the phenomenon of 'walking the band' indicates the resistance and support level of the underlying asset. In a strong trend, the price constantly attempts to touch or break through the upper/lower band along with Bollinger Bands moving towards the same direction.

For pattern recognition, Bollinger Bands has the capability of testing bottom W, top M, head-shoulder patterns, etc. With upper and lower bands served as an interval, it is easier to identify the hidden pattern in the historical data.

More details of Bollinger Bands can be found in TradingView.

10. Relative Strength Index Pattern Recognition

RSI (Relative Strength Index) is also a popular indicator. It reflects the current strength/weakness of the stock price momentum. The calculation is pretty straight forward. We use 14 days of smoothed moving average (or other moving average methods) to separately calculate the intra daily uptrend and downtrend. We denote uptrend moving average divided by downtrend moving average as the relative strength. We normalize the relative strength by 100 which becomes an index called RSI. It is commonly believed that RSI above 70 is overbought and RSI below 30 is oversold. This is the simplest way to trade on RSI (as shown in the pictures below). Nonetheless, there could be divergence between RSI momentum and price momentum which will not be covered in the script. The effectiveness of any divergence strategy on RSI is rather debatable.

If you are looking for something slightly more complex, well, we can apply pattern recognition technique to RSI as well. Unlike strategy No.9 Bollinger Bands, we can directly look at the patterns of RSI itself instead of the price. Since we have tested double bottom pattern in Bollinger Bands, we would test head-shoulder pattern on RSI this time.

11.Monte Carlo project

Monte Carlo, my first thought on these two words is the grand casino, where you meet Famke Janssen in tuxedo and introduce yourself, 'Bond, James Bond'. Indeed, the simulation is named after the infamous casino. It actually refers to the computer simulation of massive amount of random events. This unconventional mathematical method is extremely powerful in the study of stochastic process.

Here comes the argument on Linkedin that caught my eyes the other day. "Stock price can be seemed as a Wiener Process. Hence, we can use Monte Carlo simulation to predict the stock price." said a data science blog. Well, in order to be a Wiener Process, we have to assume the stock price is continuous in time. In reality, the market closes. The overnight volatility exists. But that is not the biggest issue here. The biggest issue is, can we really use Monte Carlo simulation to predict the stock price, even a range or its direction?

For more details, please refer to the read me page of a separate directory or quant trading section on my personal blog.

Here marks the debut of options strategy in this repository. Straddle refers to the shape of compasses in the payoff diagram of the strategy. A long straddle involves buying a call option and a put option at the same strike price, the same expiration date and preferably the same price. In reality, the same price is not always feasible (call options price higher implies higher upside risk, vice versa). It is recommended to trade when the price disparity between call and put options is converging.

Long straddle is commonly seen in event driven strategy, e.g. political referendum, company earning release. It profits from the uncertainty of both-side risk. For upside risk, the potential profit is unlimited. The potential loss does not come from the downside risk (there is limited gain from downside risk). Instead, it comes from the stagnant price due to insufficient volatility. In this case, short straddle is more suitable for sideways choppy market.

The crucial element of options straddle is the selection of the strike price. As the price of options contains the market consensus, the only way to maximize the profit is to find the optimal strike price to shrink the loss bandwidth. This is where the economists kick in and offer base case outlook plus best/worst scenarios. In contrast to the common misunderstanding of quantitative trading, Option Greeks are no silver bullet. Quantitative combined with fundamental in one, so-called quantamental, makes the portfolio impeccable.

13.Portfolio Optimization project

Modern portfolio theory was introduced in 1952 by Nobel laureate Harry Markowitz. It is part of investment class 101. But I watched a video by Wolfram recently. It challenged the traditional approach and introduced graph theory to asset diversification. There are plenty of quant shops deploying fancy mathematic tools to solve the market. The real question for us is, as fancy as it sounds, does graph theory work on portfolio optimization?

This project is documented in the repository of Graph Theory. For more details, please refer to the read me page of a separate directory or graph theory section on my personal blog.

STAY TUNED

展开全文
• ## python实现量化交易策略

千次阅读 多人点赞 2021-11-17 17:43:27
python实现量化交易策略 1 前言 相信大家都听说过股票，很羡慕那些炒股大佬，觉得量化投资非常高深，本文教大家用python实现简单的量化交易策略。 2 构建策略 炒股是一个概率游戏，强如巴菲特也没办法保证这只股票...

# python实现量化交易策略

## 1 前言

相信大家都听说过股票，很羡慕那些炒股大佬，觉得量化投资非常高深，本文教大家用python实现简单的量化交易策略。在这强调一下，本文仅供交流学习参考，不构成任何投资建议。炒股有风险，投资需谨慎。

## 2 构建策略

炒股是一个概率游戏，强如巴菲特也没办法保证这只股票一定能涨。我们能做的是买入上涨概率高的股票，不碰那些下跌概率高的股票。在股票市场中有很多上市公司，有些公司是领导者，有些是追随者，比如白酒行业中贵州茅台(600519)、新能源概念中宁德时代(300750)等都是领导者。我们可以观察这些股票的走势，来判断同行业同概念中其他公司股票价格的走势。基于这种思想，我们用相关性来构建策略。
本文用沪深300成分股构建股票池，样本期是2020年1月1日到2020年12月31日，数据来源于tushare数据库，官网链接：https://tushare.pro

import tushare as ts
import pandas as pd
import numpy as np
import copy

pro = ts.pro_api('你的token')
#1 获取沪深300成分股日线行情数据
def hqsj_hs():
df=pd.DataFrame()
for i in range(len(df1)):
df2 = pro.daily(ts_code=df1.iloc[i,1], start_date='20200101', end_date='20201231')
df=pd.concat([df,df2],axis=0)
df.to_excel('股票数据.xlsx',index=False)
hqsj_hs()


这里得到了沪深300成分股的日线行情数据，需要手动将excel表按股票代码和交易日期升序。有些股票在样本期某天停牌，需要剔除该股票数据。这里用A股票当天收益率和其他股票昨天收益率计算相关性。

#2 计算相关性
def xgx():
result={}
for i in range(len(df)):
key=df.iloc[i,0]
if result.get(key,False):
result[key].append(df.iloc[i,-3])
else:
result[key] = [df.iloc[i,-3]]

result1=copy.deepcopy(result)
for i in result:
if len(result[i])!=243:
del result1[i]

for i in result1:
result1[i].append([result1[i][1:],result1[i][:-1]])

result2={}
for i in result1:
aa = {}
now=pd.Series(result1[i][-1][0])
for j in result1:
pre=pd.Series(result1[j][-1][1])
xgx=now.corr(pre)
aa[j]=abs(xgx)
result2[i]=aa
#print(result2)

result3={}
for i in result2:
result3[i]={max(zip(result2[i].values(), result2[i].keys()))[1]:max(zip(result2[i].values(), result2[i].keys()))[0]}

xxx=[]
for i in result3:
for j in result3[i]:
xxx.append(result3[i][j])
b=sorted(xxx,reverse = True)[:1] #取相关性最大的

result4={}
for i in result3:
for j in result3[i]:
for x in b:
if x==result3[i][j]:
result4[i]={j:x}
print(result4)
return result4


我们取相关性最大的股票组，得到结果是上海临港(600848)和民生银行(600016)，相关性为0.4156。也就是说民生银行(600016)今天跌了，那么上海临港(600848)明天大概率要跌。我们可以在尾盘观察民生银行(600016)，如果涨了，则买入上海临港(600848)。到这里就构建了我们的策略。

## 3 买股方案

前文根据2020年1月1日到2020年12月31日的数据构建策略，用于2021年1月1日到2021年3月31日交易。

#3 获取21年数据
def test_data():
result4=xgx()
ts_code=[]
for i in result4:
for j in result4[i]:
ts_code.append(j)
df = pd.DataFrame()
for i in ts_code:
df1 = pro.daily(ts_code=i, start_date='20210101', end_date='20210331')
df = pd.concat([df, df1], axis=0)
df.to_excel('股票数据1.xlsx', index=False)
test_data()

#4 买股方案
def mgfa():
timetime=list(set(timeseries))
timetime1=sorted(timetime)
result4=xgx()
ts1=[] #昨天
ts2=[] #今天
for i in result4:
ts2.append(i)
for j in result4[i]:
ts1.append(j)

result1={}
for i in range(len(df)):
time=df.iloc[i,1]
if result1.get(time,False):
aa.append(df.iloc[i,-3])
else:
aa=[]
aa.append(df.iloc[i,-3])
result1[time]=aa

result2={}
for i in result1:
if i!=20210331:
aaa=[]
for j in result1[i]:
if j >0:
aaa.append(ts2[result1[i].index(j)])
result2[timetime1[timetime1.index(i)+1]]=aaa
print(result2)
return result2
mgfa()


我们得到了2021年1月1日到2021年3月31日的买股方案，结果为2021年1月5日空仓，2021年1月6日空仓，2021年1月7日买入上海临港(600848)等等。

## 4 评估策略

上文我们得到了买股方案，最后需要进行回测，我们用收益率，夏普率，最大回撤等指标来评估策略的优劣性，收益率和夏普率越大越好，最大回撤越小越好。

#5 获取测试数据
def cssj():
result4=xgx()
ts_code=[]
for i in result4:
ts_code.append(i)
df = pd.DataFrame()
for i in ts_code:
df1 = pro.daily(ts_code=i, start_date='20210101', end_date='20210331')
df = pd.concat([df, df1], axis=0)
df.to_excel('股票数据2.xlsx', index=False)
cssj()

#6 评估策略
def jssy():
result2=mgfa()
result4=xgx()
zdf=[]
for i in result2:
if len(result2[i]) == 1:
for j in result2[i]:
for x in range(len(df)):
if df.iloc[x, 0] == j and df.iloc[x, 1] == i:
zdf.append(df.iloc[x, -3])
else:
zdf.append(0)
bbb=1
for i in zdf:
bbb=bbb*(1+i/100)
bb=(bbb-1)*100
print('总收益率/%:',bb)
print('夏普率：', np.mean(zdf)/np.std(zdf,ddof=1))
ccc=1
hc=1
max_hc=[]
for i in zdf:
kk=ccc*(1+i/100)
if kk<ccc:
hc=hc*(1+i/100)
else:
hc=(hc-1)*100
max_hc.append(hc)
hc=1
ccc=copy.deepcopy(kk)
print('最大回撤/%:',abs(min(max_hc)))
jssy()


得到结果是收益率5.858%，夏普率0.108，最大回撤2.26%。与沪深300指数相比，2021年1月1日到2021年3月31日沪深300的收益率是-3.13%，可以看出，策略收益领先沪深300指数。

## 5 总结

本文用相关性构建一个简单的交易策略，但还有许多工作没有完成，有兴趣的读者可以进行改善。比如调参，本文用1年数据来测试1个季度，读者们可以用2年数据测试1个季度，用1年数据测试1个月等等。或者用今天和前天数据计算相关性，或者用所有上市公司代替沪深300，或者取相关性最大的5组股票等等。一个好的策略是需要不断调参不断测试的。本文的策略虽然在2020年第一季度中收益率为5.858%，但没有考虑交易费用，实际收益大约4%。再次强调，本文仅供交流学习参考，不构成任何投资建议。炒股有风险，投资需谨慎。

## 完整代码

import tushare as ts
import pandas as pd
import numpy as np
import copy

pro = ts.pro_api('你的token')
#1 获取沪深300成分股日线行情数据
def hqsj_hs():
df=pd.DataFrame()
for i in range(len(df1)):
df2 = pro.daily(ts_code=df1.iloc[i,1], start_date='20200101', end_date='20201231')
df=pd.concat([df,df2],axis=0)
df.to_excel('股票数据.xlsx',index=False)
hqsj_hs()
#股票数据.xlsx需要手动将excel表按股票代码和交易日期升序
#2 计算相关性
def xgx():
result={}
for i in range(len(df)):
key=df.iloc[i,0]
if result.get(key,False):
result[key].append(df.iloc[i,-3])
else:
result[key] = [df.iloc[i,-3]]

result1=copy.deepcopy(result)
for i in result:
if len(result[i])!=243:
del result1[i]

for i in result1:
result1[i].append([result1[i][1:],result1[i][:-1]])

result2={}
for i in result1:
aa = {}
now=pd.Series(result1[i][-1][0])
for j in result1:
pre=pd.Series(result1[j][-1][1])
xgx=now.corr(pre)
aa[j]=abs(xgx)
result2[i]=aa
#print(result2)

result3={}
for i in result2:
result3[i]={max(zip(result2[i].values(), result2[i].keys()))[1]:max(zip(result2[i].values(), result2[i].keys()))[0]}

xxx=[]
for i in result3:
for j in result3[i]:
xxx.append(result3[i][j])
b=sorted(xxx,reverse = True)[:1] #取相关性最大的

result4={}
for i in result3:
for j in result3[i]:
for x in b:
if x==result3[i][j]:
result4[i]={j:x}
print(result4)
return result4
#3 获取21年数据
def test_data():
result4=xgx()
ts_code=[]
for i in result4:
for j in result4[i]:
ts_code.append(j)
df = pd.DataFrame()
for i in ts_code:
df1 = pro.daily(ts_code=i, start_date='20210101', end_date='20210331')
df = pd.concat([df, df1], axis=0)
df.to_excel('股票数据1.xlsx', index=False)
test_data()

#4 买股方案
def mgfa():
timetime=list(set(timeseries))
timetime1=sorted(timetime)
result4=xgx()
ts1=[] #昨天
ts2=[] #今天
for i in result4:
ts2.append(i)
for j in result4[i]:
ts1.append(j)

result1={}
for i in range(len(df)):
time=df.iloc[i,1]
if result1.get(time,False):
aa.append(df.iloc[i,-3])
else:
aa=[]
aa.append(df.iloc[i,-3])
result1[time]=aa

result2={}
for i in result1:
if i!=20210331:
aaa=[]
for j in result1[i]:
if j >0:
aaa.append(ts2[result1[i].index(j)])
result2[timetime1[timetime1.index(i)+1]]=aaa
print(result2)
return result2
mgfa()
#5 获取测试数据
def cssj():
result4=xgx()
ts_code=[]
for i in result4:
ts_code.append(i)
df = pd.DataFrame()
for i in ts_code:
df1 = pro.daily(ts_code=i, start_date='20210101', end_date='20210331')
df = pd.concat([df, df1], axis=0)
df.to_excel('股票数据2.xlsx', index=False)
cssj()

#6 评估策略
def jssy():
result2=mgfa()
result4=xgx()
zdf=[]
for i in result2:
if len(result2[i]) == 1:
for j in result2[i]:
for x in range(len(df)):
if df.iloc[x, 0] == j and df.iloc[x, 1] == i:
zdf.append(df.iloc[x, -3])
else:
zdf.append(0)
bbb=1
for i in zdf:
bbb=bbb*(1+i/100)
bb=(bbb-1)*100
print('总收益率/%:',bb)
print('夏普率：', np.mean(zdf)/np.std(zdf,ddof=1))
ccc=1
hc=1
max_hc=[]
for i in zdf:
kk=ccc*(1+i/100)
if kk<ccc:
hc=hc*(1+i/100)
else:
hc=(hc-1)*100
max_hc.append(hc)
hc=1
ccc=copy.deepcopy(kk)
print('最大回撤/%:',abs(min(max_hc)))
jssy()


展开全文
• 揭秘人人都能学的量化思维投资数字货币在上一篇中，我们介绍了量化交易的一般流程、基本概念以及一些基本的策略设计思路，在这一篇中，我们将要利用上述成果，手把手教您构建第一个量化交易策略！我们以比特币作为...
• 本程序是模拟手动的方式进行同花顺客户端登录,支持下单和撤单交易,采用的方式是纯粹的键盘输入方式操作,亲测可用拒绝忽悠!
• 假设我们现在有策略A，在股票a的历史数据上进行回测后，发现能够取得稳定收益。但是我们有很长时间要等待股票a达到买入条件后，才能进行买入。这是对时间成本的严重浪费。 策略A可以在股票a上获得良好的收益，但是...
• Python量化交易】——1、封装交易所API 在刚刚过去的一个星期里，博主一直在捣鼓 Python量化交易 的内容。在写这篇文章的时候已经用python实现...【Python量化交易】——2、利用python实现网格法交易策略以及回测 【P
• 笔记（13）中介绍了在策略中对单个参数进行优化的实现方法，本文将介绍对策略中的多个参数进行优化的方案。 以笔记（14）中介绍的均线交叉策略为例，实现不同长期、短期均线参数组合的优化测试，回测股票为000001...
• DevilYuan股票量化系统由python编写，支持python3.4及以上版本，有如下功能： 可视化（基于PyQT的界面） 多线程事件引擎 四大功能 股票数据 选股 策略回测 实盘交易 历史数据均免费来自于网络 Wind免费个人接口 ...
• 日内高频交易是极其具有挑战性的交易方法，而我们想要通过科学与量化的方法来掌握它，就必须...使用C++来完善我们的交易策略，通过成熟的模型来印证，高频C++的实盘策略编写，可以让我们更加容易理解和掌握策略的精髓。
• 量化交易，就是以数学模型替代人的主观判断来制定交易策略。通常会借助计算机程序来进行策略的计算和验证，最终也常直接用程序根据策略设定的规则自动进行交易。Python 由于开发方便，工具库丰富，尤其科学计算方面...
• 博文《【实战】——基于GUI编程的python股票量化交易策略之双均线策略》利用GUI编程开发用户操作界面，以此来绘制动态的K线及双均线，实现界面动态交互效果。 学习完该实战项目后，你将掌握基于tkinter程序包开发...
• 4、Python量化交易-双均线策略笔记
• 首门程序员理财课 Python量化交易系统实战视频教程，完整版8章下载。 课程基于一个完整真实的量化交易业务来讲授，并融入老师的理财经验以及使用编程技术辅助投资的技巧，让你面对各种复杂投资情况也能做到游刃有余...
• python语言实现量化交易，以先进的数学模型替代人为的主观判断，利用计算机技术从庞大的历史数据中海选能带来超额收益的多种“大概率”事件以制定策略，极大地减少了投资者情绪波动的影响，避免在市场极度狂热或...
• 海龟交易法则属于趋势交易，首先建立唐奇安通道（下文会具体解释），即确定上突破线和下突破线，如果价格突破上线，则做多，如果价格突破下线就平仓或做空。
• python实现量化分析，交易系统，自动化运维，动态加载策略
• 在笔记（14）中，我们看到在几组回测实验中，选取5日线及60日线的金叉买入、死叉卖出策略，最终能获取最高（仅限于几组实验数据）的资产。本文将尝试选取出前一日5日线金叉60日线的股票。 实验数据截止至2020年3月20...
• Python金融分析与量化交易实战课程旨在帮助同学们快速掌握Python数据分心核心技能与交易交易系统策略部署与回测分析。 全部课程内容皆以实战为主，通俗讲解数据分析常用方法与经典解决方案。 主要包括三大核心模块...
• 第二部分：量化投资与Python 第三部分 实现简单的量化框架 开始时间、结束时间、现金、持仓数据 获取历史数据 交易函数 计算并绘制收益曲线 回测主体框架 计算各项指标 用户待写代码：初始化、每日处理函数 第四...
• 采用python语言实现的量化框架，原则尽量以简洁的语言实现金融交易等功能，系统架构清晰，方便二次开发，理论支持 股票、期货、期权等，目前只支持股票。 2.如果遇到问题，欢迎提交issue、代码，交流QQ群：...

...