阅读权限 255 威望 1 级论坛币 1457 个 通用积分 5.0477 学术水平 11 点 热心指数 14 点 信用等级 11 点 经验 3660 点 帖子 214 精华 0 在线时间 119 小时 注册时间 2016-9-24 最后登录 2020-4-8
讲师
还不是VIP /贵宾
威望 1 级论坛币 1457 个 通用积分 5.0477 学术水平 11 点 热心指数 14 点 信用等级 11 点 经验 3660 点 帖子 214 精华 0 在线时间 119 小时 注册时间 2016-9-24 最后登录 2020-4-8
经管之家送您一份
应届毕业生专属福利!
求职就业群
感谢您参与论坛问题回答
经管之家送您两个论坛币!
+2 论坛币
1. 策略原理:
( 1)获取指数 000300、 000905前一日收盘价以及前 20日数据;
( 2)计算前 20日变动;
( 3)获取 ETF300( 510300)及 ETF500( 510500)的持仓数据;
( 4)
a. 如果 000300趋势下降且有持仓,则卖出 ETF300;
b. 如果 000905趋势下降且有持仓,则卖出 ETF500;
c. 如果 300指数增幅大于 500指数增幅,且 300指数增幅大于 0,且 ETF300及 ETF500无持仓,则买入 ETF300;
d. 如果 300指数增幅小于 500指数增幅,且 500指数增幅大于 0,且 ETF300及 ETF500无持仓,则买入 ETF500;
2. 代码解读:
2.1 strategy.ini
[strategy]
username=
password=
mode=4
td_addr=localhost:8001
strategy_id=
subscribe_symbols=SHSE.000300.bar.daily,SHSE.000905.bar.daily
[backtest]
start_time = 2015-05-01 09:00:00
end_time = 2015-5-31 16:00:00
;策略初始资金
initial_cash=1000000
;委托量成交比率,默认=1(每个委托100%成交)
transaction_ratio=1
;手续费率,默认=0(不计算手续费)
commission_ratio=0
;滑点比率,默认=0(无滑点)
slippage_ratio=0
[para]
#bar_type=60
window_size=20
market_exchange_a=SHSE
market_secid_a=000300
market_exchange_b=SHSE
market_secid_b=000905
trade_exchange_a=SHSE
trade_secid_a=510300
trade_unit_a=100
trade_exchange_b=SHSE
trade_secid_b=510500
trade_unit_b=100
#hour=14
#minute=53
#sigma=2.34
##############################################################
# logger settings
##############################################################
[loggers]
keys=root
[logger_root]
level=DEBUG
handlers=console,file
[handlers]
keys=console,file
[handler_file]
class=handlers.RotatingFileHandler
;args=('strategy_sa.log','a','maxBytes=10000','backupCount=5')
args=('strategy_sa.log','a',10000,5)
formatter=simple
[handler_console]
class=StreamHandler
args = (sys.stdout,)
formatter=simple
[formatters]
keys = simple
[formatter_simple]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt= 复制代码 2.2 strategy.py
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 24 13:32:56 2017
@author: Lenovo
"""
#!/usr/bin/env python
# encoding: utf-8
from gmsdk.api import StrategyBase
import numpy as np
from collections import deque
#from gmsdk import *
#import arrow
#from math import log
eps = 1e-6
class StatArb(StrategyBase):
'''
statistics arbitrage demo
'''
def __init__(self, *args, **kwargs):
#import pdb; pdb.set_trace()
super( StatArb, self).__init__(*args, **kwargs)
# 策略初始化工作在这里写,从外部读取静态数据,读取策略配置参数等工作,只在策略启动初始化时执行一次。
# 从配置文件中读取配置参数
self.market_exchange_a = self.config.get('para', 'market_exchange_a') or 'SHSE'
self.market_secid_a = self.config.get('para', 'market_secid_a') or '000300'
self.market_symbol_a = ".".join([self.market_exchange_a, self.market_secid_a])
self.market_exchange_b = self.config.get('para', 'market_exchange_b') or 'SHSE'
self.market_secid_b = self.config.get('para', 'market_secid_b') or '000905'
self.market_symbol_b = ".".join([self.market_exchange_b, self.market_secid_b])
self.trade_exchange_a = self.config.get('para', 'trade_exchange_a') or 'SHSE'
self.trade_secid_a = self.config.get('para', 'trade_secid_a') or '510300'
self.trade_symbol_a = ".".join([self.trade_exchange_a, self.trade_secid_a])
self.trade_exchange_b = self.config.get('para', 'trade_exchange_b') or 'SHSE'
self.trade_secid_b = self.config.get('para', 'trade_secid_b') or '510500'
self.trade_symbol_b = ".".join([self.trade_exchange_b, self.trade_secid_b])
# self.hour = self.config.get('para','hour') or '14'
# self.minute = self.config.get('para','minute') or '53'
self.window_size = self.config.getint('para','window_size') or 20
self.trade_unit_a = self.config.getint('para','trade_unit_a') or 100
self.trade_unit_b = self.config.getint('para','trade_unit_b') or 100
self.closes_a_buffer = deque(maxlen=self.window_size)
self.closes_b_buffer = deque(maxlen=self.window_size)
last_closes_a = [bar.close for bar in self.get_last_n_dailybars(self.market_symbol_a,self.window_size,end_time=self.start_time)]
last_closes_a.reverse()
last_closes_b = [bar.close for bar in self.get_last_n_dailybars(self.market_symbol_b,self.window_size,end_time=self.start_time)]
last_closes_b.reverse()
self.closes_a_buffer.extend(last_closes_a)
self.closes_b_buffer.extend(last_closes_b)
def on_bar(self, bar):
if bar.sec_id == self.market_secid_a:
self.closes_a_buffer.append(bar.close)
self.last_price_a = bar.close
elif bar.sec_id == self.market_secid_b:
self.closes_b_buffer.append(bar.close)
self.last_price_b = bar.close
# t=arrow.get(bar.utc_time)
# if t.hour == self.hour and t.minute == self.minute:
self.algo_action()
def open_side_a(self):
self.open_long(self.trade_exchange_a, self.trade_secid_a, self.last_price_a, self.trade_unit_a)
#self.open_long(self.trade_exchange_a, self.trade_secid_a, 0, self.trade_unit_a)
def open_side_b(self):
self.open_long(self.trade_exchange_b, self.trade_secid_b, self.last_price_b, self.trade_unit_b)
# self.open_long(self.trade_exchange_b, self.trade_secid_b, 0, self.trade_unit_b)
def close_side_a(self):
Position_a = self.get_position(self.trade_exchange_a,self.trade_secid_a,1)
self.close_long(self.trade_exchange_a, self.trade_secid_a, self.last_price_a, Position_a.volume)
# self.close_long(self.trade_exchange_a, self.trade_secid_a, 0, Position_a.volume)
def close_side_b(self):
Position_b = self.get_position(self.trade_exchange_b,self.trade_secid_b,1)
self.close_long(self.trade_exchange_b, self.trade_secid_b, self.last_price_b, Position_b.volume)
#self.close_long(self.trade_exchange_b, self.trade_secid_b, 0, Position_b.volume)
def algo_action(self):
close_a = np.asarray(self.closes_a_buffer)
close_b = np.asarray(self.closes_b_buffer)
Change_a = (close_a[self.window_size-1]-close_a[0])/close_a[0]
Change_b = (close_b[self.window_size-1]-close_b[0])/close_b[0]
Position_a = self.get_position(self.trade_exchange_a,self.trade_secid_a,1)
Position_b = self.get_position(self.trade_exchange_b,self.trade_secid_b,1)
av = Position_a.volume if Position_a else 0
bv = Position_b.volume if Position_b else 0
diff = Change_a - Change_b
if diff > eps and Change_a > 0 and av == 0 and bv == 0:
self.open_side_a()
elif diff < eps and Change_b > 0 and av == 0 and bv == 0:
self.open_side_b()
elif Change_a < 0 and av > 0:
self.close_side_a()
elif Change_b < 0 and bv > 0:
self.close_side_b()
if __name__ == '__main__':
#import pdb; pdb.set_trace()
dm = StatArb(config_file='strategy.ini')
ret = dm.run()
print ("Statistics Arbitrage: ", ret, dm.get_strerror(ret)) 复制代码
3. Python相关函数
3.1 Python标准函数:
功能 函数原型 参数 返回值 参数名 含义 join 连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串。 'sep'.join(seq) sep 分隔符。可以为空 返回一个以分隔符sep连接各个元素后生成的字符串 seq 要连接的元素序列、字符串、元组、字典 deque Python标准库collections中的一项. 它提供了两端都可以操作的序列, 这意味着, 你可以在序列前后都执行添加或删除。 deque()
reverse 用于反向列表中元素。 list.reverse()
该方法没有返回值,但是会对列表的元素进行反向排序。 extend 该方法没有返回值,但是会对列表的元素进行反向排序。 list.extend(seq) seq 元素列表。 该方法没有返回值,但会在已存在的列表中添加新的列表内容。 append 用于在列表末尾添加新的对象。 list.append(obj) obj 添加到列表末尾的对象。 该方法无返回值,但是会修改原来的列表。
3.2 掘金接口函数:
功能 函数原型 参数 返回值 参数名 类型 说明 on_bar 响应Bar事件,收到Bar数据后本函数被调用。 on_bar(bar) bar bar bar数据 无 get_last_n_dailybars 提取单个代码的最新n条DailyBar数据, 策略类和行情服务类都提供该接口。 get_last_n_dailybars(symbol, n, end_time='') symbol string 证券代码, 带交易所代码以确保唯一,如SHSE.600000 bar列表 n int 提取的数据条数 end_time string 指定截止时间, 如2015-10-30 15:00:00 get_positions 查询当前策略指定symbol(由交易所代码和证券ID组成)和买卖方向的持仓信息。策略类和交易服务类都提供该接口。 get_position(exchange, sec_id, side); exchange string 交易所代码 Position对象,持仓信息 sec_id string 证券代码 side int 买卖方向 open_long 异步开多仓,以参数指定的symbol、价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口。 open_long(exchange, sec_id, price, volume) exchange string 交易所代码, 如上交所SHSE 委托下单生成的Order对象 sec_id string 证券代码,如浦发银行600000 price float 委托价,如果price=0,为市价单,否则为限价单 volume float 委托量 close_long 异步平多仓接口,以参数指定exchange, 证券代码sec_id, 价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口。 close_long(exchange, sec_id, price, volume) exchange string 交易所代码, 如上交所SHSE 委托下单生成的Order对象 sec_id string 证券代码,如浦发银行600000 price float 委托价,如果price=0,为市价单,否则为限价单 volume float 平仓量
4. 金融术语
二八轮动策略是基于A股市场中大盘股和小盘股走势作为信号的策略。“二”指的是权重股,大盘股;“八”指的是中小盘股,非权重股。“轮动”指的是大盘股和中小盘股之间的相互切换。一般情况下,沪深300走势表示大盘股的整体走势,中证500指数综合反映沪深证券市场内小市值公司的整体状况。
扫码加我 拉你入群
请注明:姓名-公司-职位
以便审核进群资格,未注明则拒绝
总评分: 经验 + 60
查看全部评分