【新】新手向文章 [十行代码带你量化交易入门](https://www.joinquant.com/post/3616)
#### **写在前面的话:**
使用JoinQuant编写量化策略需要具备一定的金融知识和编程基础,如果你不会使用Python编程,推荐你用几天时间学习一下这篇[Python基础教程][1]
#### **如何使用JoinQuant取数据?**
(1)取行情数据
详见:[股票行情数据](https://www.joinquant.com/post/495)
(2)取财务数据
详见:[基本面数据](https://www.joinquant.com/post/509)
#### **如何设置股票池?**
可以使用get_index_stocks、get_industry_stocks或是自行设置股票池列表。
例如:
```
# 获取所有沪深300的股票, 设为股票池
stocks = get_index_stocks('000300.XSHG')
set_universe(stocks)
```
或者指定自定义的股票池:
```
stocks = ['000009.XSHE','002222.XSHE','000005.XSHE','000002.XSHE']
set_universe(stocks)
```
#### **如何买入卖出股票?**
详见:[订单](https://www.joinquant.com/post/521)
**下订单方法**
1. order
API原文:[order](https://www.joinquant.com/api#order)
买卖一定数量(单位:股)股票。
2. order_target
API原文:[order_target](https://www.joinquant.com/api#ordertarget)
通过买卖,将股票仓位调整至一定数量(单位:股)。
3. order_value
API原文:[order_value](https://www.joinquant.com/api#ordervalue)
买卖一定价值量(单位:元)股票。
4. order_target_value
API原文:[order_target_value](https://www.joinquant.com/api#ordertargetvalue)
通过买卖,将股票仓位调整至一定价值量(单位:元)。
#### **如何止盈止损?**
context.portfolio.positions中包含持有的某个股票的信息,详见:[positions](https://www.joinquant.com/api#position)
可以使用持有的每只股票的持仓成本与当前价格实现止盈或止损,示例如下:
```
avg_cost = context.portfolio.positions[stock].avg_cost
price = context.portfolio.positions[stock].price
# 收益50%止盈
if (price/avg_cost) >= 1.5:
order_target(stock, 0)
# 亏损10%止损
if (price/avg_cost) <= 0.9:
order(stock, amount)
```
#### **如何实现一个最简单的策略?**
API文档中提供了几个策略,这几个策略包含了大部分的使用方法。
详见:[策略示例](https://www.joinquant.com/api#策略示例)
下面对用户需要实现几个函数做下简单介绍:
1. [initialize](https://www.joinquant.com/api#initialize)
初始化方法,在整个回测、模拟实盘中最开始执行一次,用于初始一些全局变量,如设置基准、交易的手续费、股票池或滑点等等。示例如下:
```
def initialize(context):
# 设定沪深300为基准
set_benchmark('000300.XSHG')
# 调用此函数设置手续费,每笔交易时的手续费是, 买入时万分之三,卖出时万分之三加千分之一印花税, 每笔交易最低扣5块钱
set_commission(PerTrade(buy_cost=0.0001, sell_cost=0.001, min_cost=5))
# 调用此函数设置滑点
set_slippage(PriceRelatedSlippage(0.002))
```
2. [handle_data](https://www.joinquant.com/api#handledata)
该函数每个单位时间会调用一次, 如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次。
函数内部就是你的交易思路,详情可参考示例代码。
3. [before_trading_start](https://www.joinquant.com/api#beforetradingstart-可选) 和 [after_trading_end](https://www.joinquant.com/api#aftertradingend-可选)(可选)
这两个函数与handle_data基本相同,只是没有传入data参数。before_trading_start 会在每天开始交易前被调用一次,而after_trading_end 会在每天结束交易后被调用一次。
#### **如何使用自定义消息?**
JoinQuant提供了微信消息推送的功能,API为[send_message](https://www.joinquant.com/api#sendmessage)
教程见:[send_message用法](https://www.joinquant.com/post/984)
##### **实例代码:**
**(1) 清仓止损(发送消息)**
```
def before_trading_start(context):
g.is_stop = dp_stoploss(kernel=2, n=10, zs=0.03)
if g.is_stop:
if len(context.portfolio.positions.keys())>0:
for stock in context.portfolio.positions.keys():
order_target(stock, 0)
send_message("清仓")
return
```
**(2) 购买股票(发送股票池)**
```
def before_trading_start(context):
g.is_stop = dp_stoploss(kernel=2, n=10, zs=0.03)
df = get_fundamentals(query(
valuation.code, valuation.market_cap
).filter(
valuation.code.in_(chosed_stocks)
).order_by(
# 按市值降序排列
valuation.market_cap.asc()
))
g.per_buylist = list(df['code'])
send_message(g.per_buylist)
```
#### **如何实现常用技术指标?**
**指数平滑均线**
```Python
# 指数平滑均线函数,以收盘价计算,可以换开盘价等其他价格,N为时间周期,m用于计算平滑系数a=m/(N+1)
def f_expma(N,m):
# 获取EXPMA初始值为回测时间段和上市交集的前N-1个收盘价均值
global init_price,EXPMA2,EXPMA1
close_price = history(N, unit='1d', field='close', security_list=None)
if init_price is None and not math.isnan(close_price[security][1]):
init_price = close_price[security].mean()#nan和N-1个数,mean为N-1个数的均值
EXPMA2 = init_price
EXPMA1 = EXPMA2
#log.info(EXPMA1)
#log.info(EXPMA2)
if not math.isnan(close_price[security][0]):
# 回测T时间,取得T-1的收盘价
current_close = close_price[security][-1]
a = m/(N+1)
EXPMA2 = a * current_close + (1 - a)*EXPMA1
log.info(EXPMA1)
log.info(EXPMA2)
return EXPMA1,EXPMA2#1为前一天值,2为后一天值
```
**MACD**
```Python
import talib
def MACD(prices, fastperiod=12, slowperiod=26, signalperiod=9):
'''
参数设置:
fastperiod = 12
slowperiod = 26
signalperiod = 9
返回: macd - signal
'''
macd, signal, hist = talib.MACD(prices,
fastperiod=fastperiod,
slowperiod=slowperiod,
signalperiod=signalperiod)
return macd[-1] - signal[-1]
```
**KDJ死叉金叉**
```Python
#定义KDJ计算函数,输入为基期长度count、平滑因子a,输出为KDJ指标值。
#K1为前一日k值,D1为前一日D值,K2为当日k值,D2为当日D值,J为当日J值
def KDJ(count,a,b,K1,D1):
h = attribute_history(security, count, unit='1d',fields=('close', 'high', 'low'),skip_paused=True)
# 取得过去count天的最低价格
low_price = h['low'].min()
# 取得过去count天的最高价格
high_price = h['high'].max()
# 取得当日收盘价格
current_close = h['close'][-1]
if high_price!=low_price:
#计算未成熟随机值RSV(n)=(Ct-Ln)/(Hn-Ln)×100
RSV = 100*(current_close-low_price)/(high_price-low_price)
else:
RSV = 50
#当日K值=(1-a)×前一日K值+a×当日RSV
K2=(1-a)*K1+a*RSV
#当日D值=(1-a)×前一日D值+a×当日K值
D2=(1-b)*D1+b*K2
#计算J值
J2 = 3*K2-2*D2
return K1,D1,K2,D2,J2
```
**RSI指数**
```Python
def calRSI(stocks):
rsi = []
for stock in stocks:
# 获取股票的收盘价数据,talib参数取14,前14天的rsi无法计算,所以取15天的数据
prices = attribute_history(stock, 15, '1d', ('close'))
# 创建RSI买卖信号,包括参数timeperiod
# 注意:RSI函数使用的price必须是narray
rsi += [talib.RSI(prices['close'].values, timeperiod=14)[-1]]
return rsi
```
**OBV指标**
```Python
#定义多空力量比率加权修正成交量的obv函数
def obv(df,init_obv):
obv1 = []
for i in range(0,len(df)):
jinge = ((df['close'].values[i]-df['low'].values[i])-(df['high'].values[i]-df['close'].values[i]))/(df['high'].values[i]-df['low'].values[i])
if i==0:
obv1.append(init_obv+jinge*df['volume'].values[i])
else:
obv1.append(obv1[-1]+jinge*df['volume'].values[i])
obv1=np.array(obv1)
return obv1
```
[1]: http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431658427513eef3d9dd9f7c48599116735806328e81000
谢谢,楼主,这个比API的那个更容易懂了
就是,还有很多基本的东西不是很清楚,如果也能像这样举个例子就好了
例如:基本面的,技术面的一些常见的指标
2016-04-06
@zhxiaobo1lu 已添加部分指标,其余指标持续添加中
2016-04-07
感谢分享,看过双均线的课程,死叉金叉略懂了,其他技术指标还是不懂,继续学习。。。
2016-05-22
@三和大神 你好,我想请问一下,如何看到单独一条语句的运行结果。
比如这条:h = history(1, '1d', 'price', security_list=[‘000300.XSHG’, ‘000001.XSHE’], df=False)
我如何看到这条运行出来的结果?谢谢你。
2016-05-22
@狂徒YOYO 抱歉,刚开始学习,还回答不来你的问题
2016-05-22
@三和大神 我问了小兵哥,后面加一条 print h 就能显示出运行结果了
2016-05-22
貌似这个版本的MACD指标算出来的数据和同花顺不太一样
2016-08-06
init_price = close_price[security].mean()
这一句有什么作用?
2016-10-26