Skip to content

ruyiqf/easyquant

This branch is 36 commits behind shidenggui/easyquant:master.

Folders and files

NameName
Last commit message
Last commit date
May 15, 2016
Jun 19, 2016
Jun 16, 2016
Jun 3, 2016
Mar 22, 2016
May 14, 2016
Apr 11, 2016
Jan 1, 2016
Jun 3, 2016
May 20, 2016
May 22, 2016
Mar 5, 2016
Apr 14, 2016
Jan 1, 2016

Repository files navigation

easyquant

基于 easytradereasyquotation 的量化交易框架

事件引擎借鉴 vnpy

交易:支持华泰、佣金宝、银河以及雪球模拟盘

行情:支持新浪免费实时行情,集思路分级基金以及 leverfun 的免费十档行情

有兴趣的可以加群 429011814 一起交流

欢迎 star && fork

相关

获取免费实时行情的类库: easyquotation

实现交易的类库: easytrader

捐助: 支付宝 微信

requirements

  • python 3.5
  • pip install -r requirements.txt

关于行情

默认使用的是 sina 的免费全市场行情,1s 推送一次

可自定义使用的行情来源或者使用 easyquotationlf 免费十档行情 和 集思路的分级基金行情

具体可参见 easyquotation

关于交易

具体可参见 easytrader

使用

准备交易账户

ht.jsonyjb.jsonyh.jsonxq.json 中填入你的账户相关信息

如何填写相关信息

快速开始

python test.py

策略编写

策略用 Python 编写后置于 strategies 文件夹下 格式可参考其中的 Demo

Hello World

# 引入策略模板
from easyquant import StrategyTemplate

# 定义策略类
class Strategy(StrategyTemplate):
    name = 'Hello World' # 定义策略名字
    
    # 策略函数,收到行情推送后会自动调用
    def strategy(self, event):
        """:param event event.data 为所有股票行情的字典,结构如下
        {'162411':
        {'ask1': '0.493',
         'ask1_volume': '75500',
         'ask2': '0.494',
         'ask2_volume': '7699281',
         'ask3': '0.495',
         'ask3_volume': '2262666',
         'ask4': '0.496',
         'ask4_volume': '1579300',
         'ask5': '0.497',
         'ask5_volume': '901600',
         'bid1': '0.492',
         'bid1_volume': '10765200',
         'bid2': '0.491',
         'bid2_volume': '9031600',
         'bid3': '0.490',
         'bid3_volume': '16784100',
         'bid4': '0.489',
         'bid4_volume': '10049000',
         'bid5': '0.488',
         'bid5_volume': '3572800',
         'buy': '0.492',
         'close': '0.499',
         'high': '0.494',
         'low': '0.489',
         'name': '华宝油气',
         'now': '0.493',
         'open': '0.490',
         'sell': '0.493',
         'turnover': '420004912',
         'volume': '206390073.351'}}
        """
        # 使用 self.user 来操作账户,用法见 easytrader 用法
        # 使用 self.log.info('message') 来打印你所需要的 log
        self.log.info('\n\n策略1触发')
        self.log.info('行情数据: 万科价格: %s' % event.data['000002'])
        self.log.info('检查持仓')
        self.log.info(self.user.balance)
效果
启动主引擎
[2015-12-28 14:05:36.649599] INFO: main_engine.py: 加载策略: 策略1_Demo
[2015-12-28 14:05:36.650250] INFO: main_engine.py: 加载策略: 策略2_Demo
[2015-12-28 14:05:36.650713] INFO: main_engine.py: 加载策略完毕
触发每秒定时计时器



策略1触发
行情数据: 万科价格:  {'ask4': 0.0, 'ask1': 0.0, 'bid2_volume': 0, 'bid3': 0.0, 'bid5_volume': 0, 'name': '万  科A', 'ask4_volume': 0, 'close': 24.43, 'volume': 0.0, 'ask3_volume': 0, 'bid5': 0.0, 'bid1': 0.0, 'ask2': 0.0, 'bid4_volume': 0, 'high': 0.0, 'ask5': 0.0, 'bid4': 0.0, 'ask5_volume': 0, 'turnover': 0, 'ask2_volume': 0, 'sell': 0.0, 'open': 0.0, 'bid3_volume': 0, 'bid2': 0.0, 'bid1_volume': 0, 'buy': 0.0, 'ask3': 0.0, 'low': 0.0, 'now': 0.0, 'ask1_volume': 0}
检查持仓
[{'asset_balance': 2758.98, 'market_value': 2740.9, 'enable_balance': 18.08, 'current_balance': 18.08, 'money_name': '人民币', 'fetch_balance': 18.08, 'money_type': '0'}]




策略2触发
行情数据: 华宝油气 {'ask4': 0.5, 'ask1': 0.497, 'bid2_volume': 4594100, 'bid3': 0.494, 'bid5_volume': 851300, 'name': '华宝油气', 'ask4_volume': 15650706, 'close': 0.5, 'volume': 138149552.799, 'ask3_volume': 19611307, 'bid5': 0.492, 'bid1': 0.496, 'ask2': 0.498, 'bid4_volume': 313700, 'high': 0.501, 'ask5': 0.501, 'bid4': 0.493, 'ask5_volume': 10108300, 'turnover': 277462973, 'ask2_volume': 10747730, 'sell': 0.497, 'open': 0.5, 'bid3_volume': 997500, 'bid2': 0.495, 'bid1_volume': 5507952, 'buy': 0.496, 'ask3': 0.499, 'low': 0.495, 'now': 0.497, 'ask1_volume': 14948518}
检查持仓
[{'asset_balance': 2758.98, 'market_value': 2740.9, 'enable_balance': 18.08, 'current_balance': 18.08, 'money_name': '人民币', 'fetch_balance': 18.08, 'money_type': '0'}]

稍显复杂的策略示例

# 引入策略模板
from easyquant import StrategyTemplate

# 定义策略类
class Strategy(StrategyTemplate):
    name = '测试策略1' # 定义策略名字
    
    def init(self):
        # 进行相关的初始化定义
        self.buy_stocks = [] # 假如一个股票一天只想买入一次。定义一个列表用来存储策略买过的股票
    
    # 策略函数,收到行情推送后会自动调用
    def strategy(self, event):
        """:param event event.data 为所有股票行情的字典,结构如下
        {'162411':
        {'ask1': '0.493',
         'ask1_volume': '75500',
         'ask2': '0.494',
         'ask2_volume': '7699281',
         'ask3': '0.495',
         'ask3_volume': '2262666',
         'ask4': '0.496',
         'ask4_volume': '1579300',
         'ask5': '0.497',
         'ask5_volume': '901600',
         'bid1': '0.492',
         'bid1_volume': '10765200',
         'bid2': '0.491',
         'bid2_volume': '9031600',
         'bid3': '0.490',
         'bid3_volume': '16784100',
         'bid4': '0.489',
         'bid4_volume': '10049000',
         'bid5': '0.488',
         'bid5_volume': '3572800',
         'buy': '0.492',
         'close': '0.499',
         'high': '0.494',
         'low': '0.489',
         'name': '华宝油气',
         'now': '0.493',
         'open': '0.490',
         'sell': '0.493',
         'turnover': '420004912',
         'volume': '206390073.351'}}
        """
        # 使用 self.user 来操作账户,用法见 easytrader 用法
        # 使用 self.log.info('message') 来打印你所需要的 log
        self.log.info('\n\n策略1触发')
        self.log.info('行情数据: 万科价格: %s' % event.data['000002'])
        self.log.info('检查持仓')
        self.log.info(self.user.balance)
        # 在未买入的情况下买入万科
        if '000002' not in self.buy_stocks:
            # self.user.buy('000002')
            self.buy_stocks.append('000002')

    # 时钟引擎,用于推送开市、收市以及其他定时事件
    def clock(self, event):
        """在交易时间会定时推送 clock 事件
        :param event: event.data.clock_event 为 [0.5, 1, 3, 5, 15, 30, 60] 单位为分钟,  ['open', 'close'] 为开市、收市
            event.data.trading_state  bool 是否处于交易时间
        """
        if event.data.clock_event == 'open':
            # 开市了
            self.log.info('open')
        elif event.data.clock_event == 'close':
            # 收市了
            self.log.info('close')
            # 收盘时清空已买股票列表 self.buy_stocks
            self.buy_stocks.clear()
        elif event.data.clock_event == 5:
            # 5 分钟的 clock
            self.log.info("5分钟")

加载指定策略

m.load_strategy(names=['测试策略2']) # 指定 names 参数,类型为列表,内容为策略的 name 属性

log system

存储日志到文件

from easyquant import DefaultLogHandler # 默认的 log handler,支持输出日志到屏幕和文件,

#  这里使用自带的 log handler, 也可使用自己编写的其他 log handler
log_handler = DefaultLogHandler(name='策略日志', log_type='file', filepath='日志文件.log')

m = easyquant.MainEngine(broker, need_data, log_handler=log_handler)
m.load_strategy()
m.start()

自定义每个策略的 log handler

除了上面使用的全局 log handler 外,还可以为每个策略定义使用的 log handler

# define your_log_handler
class Strategy(StrategyTemplate):
    ...
    def log_handler(self):
        return your_log_handler
示例: 存储每个策略的日志到不同的文件中
from easyquant import DefaultLogHandler

class Strategy(StrategyTemplate):
    ...
    def log_handler(self):
        return DefaultLogHandler(self.name, log_type='file', filepath='策略xx.log')

自定义行情引擎

允许使用自定义的其他行情,支持添加多个行情来源

修改默认 sina 行情的推送时间

from easyquant import DefaultQuotationEngine

DefaultQuotationEngine.PushInterval = 30 # 改为 30s 推送一次
m = easyquant.MainEngine(broker, need_data, quotation_engine=[DefaultQuotationEngine])

示例: 使用 lf 的十档行情

import easyquotation
from easyquant import PushBaseEngine # 引入行情引擎的基类

class LFEngine(PushBaseEngine):
    EventType = 'lf' # 指定行情的 EventType
    PushInterval = 5 # 指定行情的推送间隔, 默认为 1s

    def init(self):
        # 进行相关的初始化操作
        self.source = easyquotation.use('lf')

    def fetch_quotation(self):
        # 返回行情
        return self.source.stocks(['162411', '000002'])
m = easyquant.MainEngine(broker, need_data, quotation_engine=[LFEngine])

使用多个行情来源

可同时使用多个行情引擎,此时在策略中使用 event.event_type 来区分行情来源

from easyquant import DefaultQuotationEngine

m = easyquant.MainEngine(broker, need_data, quotation_engine=[DefaultQuotationEngine, LFEngine, OtherEngine])

About

简单的股票量化框架

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%