引言
一些用户是从通达信等软件上切换过来的,对于掘金框架及python语言不是很了解,很难上手。对此,小编整理了一些基本要点以及一些简单的示例,希望对大家有帮助。
从结构开始说起
通达信这类软件在编写公式之前首先要确定一个频率,是日线级别、分钟级别还是其他级别,然后再定义公式,这个选择的过程对应掘金python语句中的订阅函数(subscribe)。如果在通达信中选择日线频率,在掘金中就订阅’1d’频率。(特别说明,掘金除了bar数据,还支持tick级别的数据,用户可以在更高频率下编写策略)。
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=2)
确定好标的和频率以后就到了策略的主体部分,在通达信就表示为各种各样的公式,在掘金中需要将这些公式翻译成对应的python语言。公式翻译完成后,将翻译后的逻辑写在on_bar或on_tick里面。
什么是on_bar?
On_bar称为数据推送事件,和订阅函数配套使用,只有订阅了才会触发on_bar。每返回一根新的bar,就会驱动一次。可以将on_bar想象成一根又一根推过来的k线,通达信中的函数是对单根k线使用的,到了掘金中就转化为在on_bar里面编写函数。
一些不同点:
不同点1:通达信和掘金都是对获取的数据进行操作,通达信将其封装成易懂的函数,掘金将其直接暴露出来,让用户对原始数据进行提取、分析等,所以部分通达信函数在python中可以直接以索引形式获得,不需要再编写函数。
这些数据都包含哪些呢?
主要包括以下几个字段:开盘价、收盘价、最高价、最低价、成交额、成交量、持仓量。
这些字段的引用方式:
先用context.data()接口将订阅的数据提取出来,取出是dataframe格式。提取对应的字段用:data[‘字段名’]的形式。
high = data['high'] # 最高价
close = data['close'] # 收盘价
low = data['low'] # 最低价
open = data['open'] # 开盘价
提取出对应字段后发现,取出的数据并非单个数据,而是一列数据,这就出现了另一个引用上的不同之处。
不同点2:
在通达信中有一个REF(N)函数,用来表示滞后N期的数据,REF(CLOSE,1)就表示滞后1期的收盘价。转化到python中,需要用索引的方式直接取出前一期数据。比如:REF(CLOSE,1)在python中表示为CLOSE.iloc[-2],意思为CLOSE的倒数第二个元素,即CLOSE的前一期元素。(因为CLOSE的最后一个元素是当前日期的数据,倒数第二个元素才是前一日的数据,所以选择倒数第二个元素)
Tips : iloc的用法
iloc表示索引引用方法,使用方式为:df.iloc[m,n],表示df第m行n列的数据。如果df是一维数据,则df.iloc[n]表示df第n个数据。
整体结构示例:
举个例子:今天成交量比昨天成交量放大了1倍,则买入1手。
思路:
先确定频率(昨天、今天字样说明频率是日频),则先订阅’1d’的数据。
然后在on_bar里面写逻辑。
首先需要今日成交量、昨日成交量两个数据,直接在data里面获取。
然后写if条件,当满足今天成交量比昨天放大1倍,则开始下单。
最后,运行策略。
完成后就如下图所示:
# 今天成交量比昨天成交量放大了1倍,则买入1手
# 通达信: VOL/REF(VOL,1)>2
# 掘金python
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=2)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=2) # 获取订阅的数据
vol_today = data['volume'].iloc[-1] # 昨日成交量
vol_yesterday = data['volume'].iloc[-2] # 今日成交量
if vol_today/vol_yesterday > 2:
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
这就是一个简单的示例。
还有一些简单的练习,使用者可以参考一下。
# 例1:今天5日均量比昨天的5日均量放大了1倍,则买入1手
# 通达信: AA:=MA(VOL,5) BB:REF(AA,1) AA/BB > 2
# 掘金python
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=6)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=6) # 获取订阅的数据
vol_today_mean = np.mean(data['volume'].iloc[-1:-5]) # 昨日成交量
vol_yesterday_mean = np.mean(data['volume'].iloc[-2:-6]) # 今日成交量
if vol_today_mean/vol_yesterday_mean > 2:
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例2:连续3天增量1倍以上,则买入1手
# 通达信:EVERY(V>= REF(V,1)*2,3)
# 掘金python
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=6)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=6) # 获取订阅的数据
data['vol_change'] = data['volume'] - data.volume.shift(1) # 计算增量
if np.all(data['vol_change'].iloc[-3:] > data.volume.shift(1).iloc[-3:])*2: # 等价于 EVERY(V>= REF(V,1)*2,3)
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例3:涨幅达到7%以上,则买入1手
# 通达信:CLOSE/REF(CLOSE,1) > 1.07
# 掘金python
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=2)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=2) # 获取订阅的数据
data['price_change'] = data['close'] - data['close'].shift(1) # 计算涨幅或跌幅
if data['price_change'].iloc[-1] > 0.07: # 等价于 CLOSE/REF(CLOSE,1) > 1.07
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例4:向上跳空,则买入1手
# 通达信:OPEN>REF(HIGH,1)
# 掘金python
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=2)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=2) # 获取订阅的数据
if data['open'].iloc[-1] > data['close'].iloc[-2]: # 等价于 OPEN>REF(HIGH,1)
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例5:收盘价 > 1日前的25日内收盘价的最低值,则买入1手
# 通达信:c > ref(llv(c,25),1)
# 掘金python
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=25)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=25) # 获取订阅的数据
if data['close'].iloc[-1] <= data['close'].iloc[-2:].min(): # 等价于c > ref(llv(c,25),1)
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例6:横盘整理时(10日收盘价振幅在5%以内波动)清仓
# 通达信:(HHV(CLOSE,10)-LLV(CLOSE,10))/CLOSE < 0.05
# 掘金python
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=10)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=10) # 获取订阅的数据(最近10日)
if (data['close'].max() - data['close'].min())/data['close'].iloc[-1] < 0.05: # (HHV(CLOSE,10)-LLV(CLOSE,10))/CLOSE < 0.05
order_target_volume(symbol=context.symbol, volume=0, position_side=PositionSide_Long,
order_type=OrderType_Market)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例7:阴转阳,买入1手
# 通达信公式:ref(c,1) < ref(o,1) and c > 0
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=2)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=2) # 获取订阅的数据(最近10日)
if (data['close'].iloc[-2] < data['open'].iloc[-2]) and \
(data['close'].iloc[-1] > data['open'].iloc[-1]): # (HHV(CLOSE,10)-LLV(CLOSE,10))/CLOSE < 0.05
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例8:当前价格上穿20日均线,买入1手
# 通达信公式:cross(c,ma(c,20))
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=21)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=21) # 获取订阅的数据(最近21日)
data['MA20'] = data['close'].rolling(20).mean()
if (data['close'].iloc[-1] > data['MA20'].iloc[-1]) and (data['close'].iloc[-2] < data['MA20'].iloc[-2]): # cross(c,ma(c,20))
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例9:金叉买入:5日均线上穿20日均线,买入1手
# 通达信公式:cross(ma(c,5),ma(c,20))
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=21)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=21) # 获取订阅的数据(最近21日)
data['MA5'] = data['close'].rolling(5).mean() # 求5日均线
data['MA20'] = data['close'].rolling(20).mean() # 求20日均线
if (data['MA5'].iloc[-1] > data['MA20'].iloc[-1]) and (data['MA5'].iloc[-2] < data['MA20'].iloc[-2]): # 等价cross(ma(c,5),ma(c,20))
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例10:下影线长于上影线,买入1手
# 通达信公式:(c-l) > (h-c)
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=10)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=10) # 获取订阅的数据(最近21日)
if (data['close'].iloc[-1] - data['low'].iloc[-1] > data['high'].iloc[-1] - data['close'].iloc[-1]) > 0:
# 等价于 (c-l) > (h-c)
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例11:乌云压顶则清仓
# 通达信公式:
# AA:=REF(C,1) > REF(O,1) # 昨日收阳
# BB:=O>REF(C,1) # 高开
# CC:=C<(REF(C,1)-REF(O,1))/2+REF(O,1) # 盖顶低收
# DD:IF(AA AND BB AND CC,1,0)
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=2)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=2) # 获取订阅的数据(最近2日)
if (data['close'].iloc[-2] > data['open'].iloc[-2]) and \
(data['open'].iloc[-1] > data['close'].iloc[-2]) and \
(data['close'].iloc[-1] < ((data['close'].iloc[-2] - data['open'].iloc[-2])/2 + data['open'].iloc[-2])):
order_target_volume(symbol=context.symbol, volume=0, position_side=PositionSide_Long,
order_type=OrderType_Market)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例12:双均线选股
# 通达信公式:
# MA1: = MA(CLOSE,5)
# MA2: = MA(CLOSE,10)
# XG: C > 1.005 * MA2 AND CROSS(MA1,MA2) AND MA1 > MA2
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=20)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=20) # 获取订阅的数据(最近20日)
close = data['close']
# 利用talib库计算长短周期均线
ma1 = talib.SMA(close.values.reshape(20), 5)
ma2 = talib.SMA(close.values.reshape(20), 10)
# 如果满足条件,则买入100股
if (close.iloc[-1] > 1.005 * ma2.iloc[-1]) and (ma1.iloc[-2] < ma2.iloc[-2])\
and (ma1.iloc[-1] > ma2.iloc[-1]):
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
#例13:黄昏之星出现,平仓
#通达信公式:
# a1:=open
# a2:=close
# a3:=high
# b1:=ref(open,1)
# b2:=ref(close,1)
# b3:=ref(high,1)
# b4:=ref(low,1)
# c1:=ref(open,2)
# c2:=ref(close,2)
# c3:=ref(high,2)
# c4:=ref(low,2)
# aa:=a1<b2 and a1/a2>1.04
# bb:=b1>c3 and b2>c3 and abs(b1-b2)/b1<0.01 and b3>b1 and # b3>b2 and b4<b1 and b4<b2 and b3=hhv(high,20)
# cc:=c2/ref(close,3)>1.04 and c2>c1
# aa and bb and cc
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=3)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=3) # 获取订阅的数据(最近20日)
# 提取a1,a2,a3,b1,b2,b3,b4,c1,c2,c3,c4
a1 = data['open'].iloc[-1]
a2 = data['close'].iloc[-1]
b1 = data['open'].iloc[-2]
b2 = data['close'].iloc[-2]
b3 = data['high'].iloc[-2]
b4 = data['low'].iloc[-2]
c1 = data['open'].iloc[-3]
c2 = data['close'].iloc[-3]
c3 = data['high'].iloc[-3]
# 如果满足条件,则买入100股
if (a1 < b2) and (a1/a2 > 1.04) and \
(b1 > c3) and (b2 > c3) and (np.abs(b1-b2)/b1 < 0.01) and (b3 > b1) and (b4 < b1) and (b4 < b2) and (b3 == data['high'].iloc[-20:]) \
and (c2/data['close'].iloc[-4] > 1.04) and (c2 > c1):
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
# 例14:突破底部横盘整理创新高——买入100股
# 对应通达信公式
# V1:=MA(VOL,5);
# V2:=VOL/REF(V1,1)>2;
# PZ1:=MA(CLOSE,M);
# PZ2:=HHV(HIGH,M);
# PZ3:=LLV(LOW,M);
# PZ4:=(PZ2-PZ1)/PZ1;
# PZ5:=(PZ1-PZ3)/PZ1;
# PZ:=REF(PZ4,1)<0.15 AND REF(PZ5,1)<0.15;
# TP1:HHV(HIGH,M);
# TP:=HIGH=TP1;
# V2 AND PZ AND TP;
# 掘金python:
def init(context):
# 定义标的
context.symbol = 'SHSE.600519'
# 订阅bar数据,获取成交量
subscribe(symbols=context.symbol, frequency='1d', count=200)
def on_bar(context, bars):
data = context.data(symbol=context.symbol, frequency='1d', count=200)
# 计算今量/昨日的5日均量
v2 = data['volume'].iloc[-1]/np.mean(data['volume'].iloc[-6:-1])
# 计算昨日150日最高价和150日均价的距离的百分比
pz1 = np.mean(data['close'].iloc[-151:-1]) # 昨日的150日均价
pz2 = np.max(data['high'].iloc[-151:-1]) # 昨日的150日最高价
pz3 = np.max(data['high'].iloc[-151:-1]) # 昨日的150日最低价
pz4 = (pz2-pz1)/pz1
pz5 = (pz1-pz3)/pz1
# 进入判断条件:V2 AND PZ AND TP
if (v2 > 2) and (pz4 < 0.15) and (pz5 < 0.15) and (data['high'].iloc[-1] == np.max(data['high'].iloc[-151:-1])):
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
if __name__ == '__main__':
run(strategy_id='请输入你的策略id',
filename='main.py',
mode=MODE_BACKTEST,
token='请输入你的token',
backtest_start_time='2020-12-01 08:00:00',
backtest_end_time='2020-12-20 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001
)
来源:掘金量化社区 作者:四两