请选择 进入手机版 | 继续访问电脑版
楼主: 唉人好累66
1455 3

[原创博文] 从零开始学量化:04阿尔法策略 [推广有奖]

  • 0关注
  • 41粉丝

讲师

55%

还不是VIP/贵宾

-

威望
1
论坛币
1457 个
通用积分
5.0477
学术水平
11 点
热心指数
14 点
信用等级
11 点
经验
3660 点
帖子
214
精华
0
在线时间
119 小时
注册时间
2016-9-24
最后登录
2020-4-8

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
1. 策略原理:
    始终买入沪深300中市值最小的5只
    先订阅000300分钟行情(也可订阅其他symbol,只是用来作行情触发)
    第一个bar行情到来时在md_init中选股
    选出股票池与持仓作对比
    无持仓时直接按照股票池等权买入
    有持仓时,不在股票池中的股票卖出
    在成交回报on_order_filled中判断是否都已卖出,卖出仓位都成交以后再买入。


2. 代码解读:
    2.1 Alpha.py
  1. # !/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from gmsdk.api import StrategyBase


  4. class Alpha(StrategyBase):

  5.     def __init__(self, *args, **kwargs):
  6.         super(Alpha, self).__init__(*args, **kwargs)
  7.         self.buy_dict = {}
  8.         self.sell_dict = {}
  9.         self.is_traded = False

  10.     def initialize(self):
  11.         pass

  12.     # 收到第一根Bar后交易
  13.     def on_bar(self, bar):
  14.         print(bar.strtime)
  15.         if self.is_traded:
  16.             return
  17.         self.is_traded = True
  18.         self.initialize()
  19.         self.handle_data()

  20.     def handle_data(self):
  21.         pass

  22.     def on_order_filled(self, order):
  23.         if order.sec_id in self.sell_dict and order.strategy_id == self.strategy_id:
  24.             self.sell_dict.pop(order.sec_id)
  25.             if len(self.sell_dict) == 0:  # 由于资金每次都开满,等卖盘全部成交资金回流时再买入
  26.                 cash = self.get_cash()
  27.                 for bar in self.buy_dict.values():
  28.                     vol = int(cash.available * 0.95 / len(self.buy_dict) / bar.close / 100) * 100
  29.                     self.open_long(bar.exchange, bar.sec_id, 0, vol)
复制代码
   2.2 small_market_value.py
  1. # !/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from Alpha import Alpha

  4. '''
  5. 请在Strategy中修改个人账号密码和策略ID
  6. '''

  7. class Strategy(Alpha):
  8.     def __init__(self, *args, **kwargs):
  9.         super(Strategy, self).__init__(*args, **kwargs)
  10.         self.md.subscribe('SHSE.000300.bar.60')  # 订阅一个symbol,在交易时间触发下单

  11.     def initialize(self):
  12.         # region 获取沪深300中当天可交易的股票
  13.         instruments1 = self.get_instruments('SHSE', 1, 1)
  14.         instruments2 = self.get_instruments('SZSE', 1, 1)
  15.         symbol_list1 = set(instrument.symbol for instrument in instruments2 + instruments1)  # 获取当日可交易的股票,剔除B股
  16.         constituents = self.get_constituents('SHSE.000300')
  17.         symbol_list2 = set(constituent.symbol for constituent in constituents)  # 获取沪深300成分股(剔除ST、*ST股票,以及上市时间不足3个月等股票后剩余的股票)
  18.         symbol_list = symbol_list1 & symbol_list2
  19.         symbol_list = ','.join(symbol for symbol in symbol_list)
  20.         # endregion

  21.         # region 选出市值最小的5只
  22.         market_index = self.get_last_market_index(symbol_list)
  23.         data = [mi for mi in market_index]
  24.         data = sorted(data, key=lambda mi: mi.market_value)[:5]  # 市值最小的5只
  25.         # endregion

  26.         # region 为了计算仓位,获取昨日dailybar,存入buy_dict
  27.         buy_list = ','.join(d.symbol for d in data)
  28.         dailybars = self.get_last_dailybars(buy_list)
  29.         self.buy_dict = {dailybar.sec_id: dailybar for dailybar in dailybars}
  30.         # endregion


  31.     def handle_data(self):
  32.         # region 没有持仓时直接open_long
  33.         print(self.buy_dict.keys())
  34.         positions = self.get_positions()
  35.         if len(positions) == 0:
  36.             cash = self.get_cash()
  37.             for b in self.buy_dict.values():
  38.                 vol = int(cash.available * 0.95 / len(self.buy_dict) / b.close / 100) * 100
  39.                 self.open_long(b.exchange, b.sec_id, 0, vol)
  40.             return
  41.         # endregion

  42.         # region 有持仓时结合持仓获取buy_dict,sell_dict
  43.         for p in positions:
  44.             if p.sec_id in self.buy_dict:
  45.                 self.buy_dict.pop(p.sec_id)
  46.             else:
  47.                 self.sell_dict[p.sec_id] = p
  48.         # endregion

  49.         for p in self.sell_dict.values():  # 先卖出,卖盘成交时再买入,若资金足够也可以直接买入
  50.             self.close_long(p.exchange, p.sec_id, 0, p.volume)

  51.     def on_order_status(self, order):
  52.         pass

  53. if __name__ == '__main__':
  54.     my_strategy = Strategy(
  55.         username='username',  # 请修改账号
  56.         password='password',  # 请修改密码
  57.         strategy_id='strategy_id',  # 请修改策略ID
  58.         mode=2,
  59.         td_addr='localhost:8001')
  60.     ret = my_strategy.run()
  61.     print('exit code: ', ret)
复制代码
3. Python相关函数
    3.1 Python标准函数:
功能函数原型参数返回值
参数名含义
join连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串'sep'.join(seq)sep分隔符。可以为空返回一个以分隔符sep连接各个元素后生成的字符串
seq要连接的元素序列、字符串、元组、字典
sorted排序sorted(iterable, cmp=None, key=None, reverse=False)iterableiteralbe指的是能够一次返回它的一个成员的对象。iterable主要包括3类: 第一类是所有的序列类型,比如list(列表)、str(字符串)、tuple(元组)。 第二类是一些非序列类型,比如dict(字典)、file(文件)。 第三类是你定义的任何包含__iter__()或__getitem__()方法的类的对象。
cmpcmp: 指定一个定制的比较函数,这个函数接收两个参数(iterable的元素),如果第一个参数小于第二个参数,返回一个负数;如果第一个参数等于第二个参数,返回零;如果第一个参数大于第二个参数,返回一个正数。默认值为None。
keykey:指定一个接收一个参数的函数,这个函数用于从每个元素中提取一个用于比较的关键字。默认值为None。
reversereverse:是一个布尔值。如果设置为True,列表元素将被降序排列,默认为升序排列。 通常来说,key和reverse比一个等价的cmp函数处理速度要快。这是因为对于每个列表元素,cmp都会被调用多次,而key和reverse只被调用一次。
3.2 掘金接口函数:
[tr][/tr]
功能函数原型参数返回值
参数名类型说明
get_instruments提取交易代码。策略类和行情服务类都提供该接口。get_instruments(exchange, sec_type, is_active)exchangestring交易所代码Instrument对象列表
sec_typeint代码类型:1.股票,2.基金,3.指数,4.期货,5.ETF
is_activeint当天是否交易:1.是,0.否
get_constituents提取指数的成分股代码。策略类和行情服务类都提供该接口。get_constituents(index_symbol)index_symbolstring指数代码constituent对象列表
get_last_market_index按时间周期提MarketIndex,按时间升序排列。策略类和行情服务类都提供该接口。get_last_market_index(symbol_list)symbol_liststring多个品种代码列表,如SHSE.600000,SZSE.000001MarketIndex对象列表
get_last_dailybars提取最新1条DailyBar数据,支持单个代码提取或多个代码组合提取。策略类和行情服务类都提供该接口。get_last_dailybars(symbol_list)symbolstring证券代码, 带交易所代码以确保唯一,如SHSE.600000,同时支持多只代码DailyBar列表
get_positions查询当前策略指定symbol(由交易所代码和证券ID组成)和买卖方向的持仓信息。策略类和交易服务类都提供该接口。get_position(exchange, sec_id, side);exchangestring交易所代码Position对象,持仓信息
sec_idstring证券代码
sideint买卖方向
get_cash查询当前策略的资金信息,策略类和交易服务类都提供该接口。get_cash()Cash对象,当前策略的资金信息
open_long异步开多仓,以参数指定的symbol、价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口open_long(exchange, sec_id, price, volume)exchangestring交易所代码, 如上交所SHSE委托下单生成的Order对象
sec_idstring证券代码,如浦发银行600000
pricefloat委托价,如果price=0,为市价单,否则为限价单
volumefloat委托量
close_long异步平多仓接口,以参数指定的exchange, 证券代码sec_id, 价和量下单。如果价格为0,为市价单,否则为限价单。策略类和交易服务类都提供该接口。close_long(exchange, sec_id, price, volume)exchangestring交易所代码, 如上交所SHSE委托下单生成的Order对象
sec_idstring证券代码,如浦发银行600000
pricefloat委托价,如果price=0,为市价单,否则为限价单
volumefloat平仓量

4. 金融术语:
阿尔法策略:投资者在市场交易中面临着系统性风险(即贝塔或Beta、β风险)和非系统性风险(即阿尔法或Alpha、α风险),通过对系统性风险进行度量并将其分离,从而获取超额绝对收益(即阿尔法收益)的策略组合,即为阿尔法策略。从广义上讲,获取阿尔法收益的投资策略有很多种,其中既包括传统的基本面分析选股策略、估值策略、固定收益策略等等,也包括利用衍生工具对冲掉贝塔风险、获取阿尔法收益的可转移阿尔法策略。后者在国内通常被称为阿尔法对冲策略,并在近年A股市场上得到广泛应用。本策略只是展示了选股策略,并没有将贝塔风险对冲。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:从零开始 阿尔法 Instruments Instrument positions

已有 1 人评分经验 收起 理由
残阳_等待 + 100 精彩帖子

总评分: 经验 + 100   查看全部评分

顶顶顶~好贴莫沉

使用道具

后续还会继续上干货策略,好东西希望和大家一起分享,如果想了解更多精彩的量化方面的内容进入证经社——http://zjshe.cn/q/forum.php?gid=36了解更多吧~

使用道具

感谢分享

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-3-29 12:38