diff --git a/.gitignore b/.gitignore index 5b989dd4..0b894ab8 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,7 @@ vn.trader/ctaStrategy02.py *.pyd vn.trader/vnctpmd.pyd_old *.pyd_old +vn.trader/ctaStrategy06.py +vn.trader/ctaStrategy03.py +vn.trader/ctaStrategy05.py +vn.trader/ctaStrategy04.py diff --git a/vn.trader/main.py b/vn.trader/main.py new file mode 100644 index 00000000..a84e5493 --- /dev/null +++ b/vn.trader/main.py @@ -0,0 +1,64 @@ +# encoding: UTF-8 +import time +import sys +import ctypes +try: + import bsddb +except: + import bsddb3 as bsddb + sys.modules['bsddb'] = bsddb +import json +from ctaStrategies import strategyClassDict + + +from vtEngine import MainEngine +from PyQt4.QtCore import QCoreApplication +from simple_monitor import * +from setup_logger import setup_logger + +setup_logger(debug=True) +# ---------------------------------------------------------------------- +def main(): + app = QCoreApplication(sys.argv) + mainEngine = MainEngine() + mainEngine.dbConnect() + mainEngine.connect('CTP_Prod') + + + def loadStrategySetting(setting_file_name): + """读取引擎中的策略配置""" + with open(setting_file_name) as f: + # 读取文件内容串=》Json对象 + d = json.load(f) + + # 策略实例名称,配置内容 + for name, setting in d.items(): + + # 策略的类名称 + strategyClassName = setting['strategyClassName'] + + if strategyClassName in strategyClassDict: + # 透过策略类字典,反射获取策略 + strategyClass = strategyClassDict[strategyClassName] + + # 初始化策略的设置 + mainEngine.ctaEngine.initStrategy(name, strategyClass, setting) + else: + mainEngine.writeLog(u'无法找到策略类:' + strategyClassName) + break + + loadStrategySetting('CTA_setting.json') + mainEngine.ctaEngine.startStrategy('Test1') + logM = LogMonitor(mainEngine.eventEngine) + errorM = ErrorMonitor(mainEngine.eventEngine) + tradeM = TradeMonitor(mainEngine.eventEngine) + orderM = OrderMonitor(mainEngine.eventEngine, mainEngine) + positionM = PositionMonitor(mainEngine.eventEngine) + accountM = AccountMonitor(mainEngine.eventEngine) + + + app.exec_() + + +if __name__ == '__main__': + main() diff --git a/vn.trader/setup_logger.py b/vn.trader/setup_logger.py new file mode 100644 index 00000000..9df96b46 --- /dev/null +++ b/vn.trader/setup_logger.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python +# coding=utf8 +import logging +import threading +import logging.config +import os.path +import uuid +from logging import handlers + + +SIMPLE_FORMAT = "[%(asctime)s] %(message)s" +RECORD_FORMAT = "[%(asctime)s.%(msecs)d][%(filename)s:%(lineno)d][%(process)d:%(threadName)s] %(message)s" +COLOR_FORMAT = { + 'DEBUG': "\033[1;34m%(levelname)s\033[0m: ", + 'INFO': "\033[1;32m%(levelname)s\033[0m: ", + 'WARNING': "\033[1;33m%(levelname)s\033[0m: ", + 'ERROR': "\033[1;31m%(levelname)s\033[0m: ", +} +DATE_FORMAT = "%Y-%m-%d %H:%M:%S" + + +class ExtFormatter(logging.Formatter): + + def __init__(self, colorful=False, simple=False): + self._colorful = colorful + self._simple = simple + logging.Formatter.__init__(self, datefmt=DATE_FORMAT) + + def format(self, record): + fmt = SIMPLE_FORMAT if self._simple else RECORD_FORMAT + if self._colorful: + self._fmt = COLOR_FORMAT[record.levelname] + fmt + else: + self._fmt = "%(levelname)s: " + fmt + return logging.Formatter.format(self, record) + + +class BasicFormatter(ExtFormatter): + + def __init__(self): + super(BasicFormatter, self).__init__() + + +class SimpleFormatter(ExtFormatter): + + def __init__(self): + super(SimpleFormatter, self).__init__(simple=True) + + +class ColorFormatter(ExtFormatter): + + def __init__(self): + super(ColorFormatter, self).__init__(colorful=True) + + +thread_data = threading.local() + + + +class StreamHandler(logging.StreamHandler): + def acquire(self): + pass + + def release(self): + pass + +class FileHandler(handlers.TimedRotatingFileHandler): + def acquire(self): + pass + + def release(self): + pass + + +def setup_logger(filename=None, debug=False): + handlers = [] + LOGGING = { + 'version': 1, + 'disable_existing_loggers': True, + 'formatters': { + 'color': { + '()': ColorFormatter, + }, + 'basic': { + '()': BasicFormatter, + }, + }, + 'handlers': { + 'std_debug': { + 'level': 'DEBUG', + '()': StreamHandler, + 'formatter': 'basic', + }, + 'std_info': { + 'level': 'INFO', + '()': StreamHandler, + 'formatter': 'basic', + } + }, + 'loggers': { + '': { + 'level': 'DEBUG', + 'handlers': [], + 'propagate': True, + }, + 'tornado.access': { + 'level': 'DEBUG', + 'handlers': [], + 'propagate': False, + }, + 'tornado.application': { + 'level': 'DEBUG', + 'handlers': [], + 'propagate': False, + }, + 'tornado.gen_log': { + 'level': 'DEBUG', + 'handlers': [], + 'propagate': False, + }, + 'django': { + 'handlers': [], + 'propagate': True, + 'level': 'INFO', + }, + 'django.request': { + 'handlers': [], + 'level': 'INFO', + 'propagate': False, + }, + }, + } + + if filename: + base_name, ext = os.path.splitext(filename) + debug_filename = '%s-debug%s' % (base_name, ext) + local = { + 'local_debug': { + 'level': 'DEBUG', + '()': FileHandler, + 'filename': debug_filename, + 'formatter': 'basic', + 'interval': 1, + 'when': 'D', + }, + 'local_info': { + 'level': 'INFO', + '()': FileHandler, + 'filename': filename, + 'formatter': 'basic', + 'interval': 1, + 'when': 'D', + }, + + } + + LOGGING['handlers'].update(local) + handlers.append('local_info') + if debug: + handlers.append('local_debug') + else: + if debug: + handlers.append('std_debug') + else: + handlers.append('std_info') + + for k, v in LOGGING['loggers'].items(): + v['handlers'] = handlers + + logging.config.dictConfig(LOGGING) + return LOGGING + +if __name__ == '__main__': + setup_logger('aaa.log', debug=True) + logging.info("aaaa") \ No newline at end of file diff --git a/vn.trader/simple_monitor.py b/vn.trader/simple_monitor.py new file mode 100644 index 00000000..033afed0 --- /dev/null +++ b/vn.trader/simple_monitor.py @@ -0,0 +1,291 @@ +# encoding: UTF-8 + +from collections import OrderedDict + +from PyQt4 import QtGui, QtCore + +from eventEngine import * +from vtFunction import * +from vtGateway import * +import logging + + +######################################################################## +class BasicMonitor(object): + """ + 基础监控 + + headerDict中的值对应的字典格式如下 + {'chinese': u'中文名', 'cellType': ""} + + """ + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine=None, parent=None): + self.eventEngine = eventEngine + + # 保存表头标签用 + self.headerDict = OrderedDict() # 有序字典,key是英文名,value是对应的配置字典 + self.headerList = [] # 对应self.headerDict.keys() + + # 保存相关数据用 + self.dataDict = {} # 字典,key是字段对应的数据,value是保存相关单元格的字典 + self.dataKey = '' # 字典键对应的数据字段 + + # 监控的事件类型 + self.eventType = '' + + # 保存数据对象到单元格 + self.saveData = False + + # ---------------------------------------------------------------------- + def setHeaderDict(self, headerDict): + """设置表头有序字典""" + self.headerDict = headerDict + self.headerList = headerDict.keys() + + # ---------------------------------------------------------------------- + def setDataKey(self, dataKey): + """设置数据字典的键""" + self.dataKey = dataKey + + # ---------------------------------------------------------------------- + def setEventType(self, eventType): + """设置监控的事件类型""" + self.eventType = eventType + + # ---------------------------------------------------------------------- + def setSaveData(self, saveData): + """设置是否要保存数据到单元格""" + self.saveData = saveData + + # ---------------------------------------------------------------------- + def registerEvent(self): + self.eventEngine.register(self.eventType, self.updateEvent) + + # ---------------------------------------------------------------------- + def updateEvent(self, event): + """收到事件更新""" + data = event.dict_['data'] + self.updateData(data) + + # ---------------------------------------------------------------------- + def updateData(self, data): + """将数据更新到表格中""" + s = [] + for header, value in self.headerDict.items(): + v = getattr(data, header) + if isinstance(v, basestring) and not isinstance(v, unicode): + try: + v = v.decode('gbk') + except: + v = v.decode('utf8') + s.append('%s: %s' % (value['chinese'], v)) + logging.info(' '.join(s)) + + +######################################################################## +class MarketMonitor(BasicMonitor): + """市场监控组件""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, parent=None): + """Constructor""" + super(MarketMonitor, self).__init__(eventEngine, parent) + + # 设置表头有序字典 + d = OrderedDict() + d['symbol'] = {'chinese': u'合约代码', 'cellType': ""} + d['vtSymbol'] = {'chinese': u'名称', 'cellType': ""} + d['lastPrice'] = {'chinese': u'最新价', 'cellType': ""} + d['volume'] = {'chinese': u'成交量', 'cellType': ""} + d['openInterest'] = {'chinese': u'持仓量', 'cellType': ""} + d['openPrice'] = {'chinese': u'开盘价', 'cellType': ""} + d['highPrice'] = {'chinese': u'最高价', 'cellType': ""} + d['lowPrice'] = {'chinese': u'最低价', 'cellType': ""} + d['bidPrice1'] = {'chinese': u'买一价', 'cellType': ""} + d['bidVolume1'] = {'chinese': u'买一量', 'cellType': ""} + d['askPrice1'] = {'chinese': u'卖一价', 'cellType': ""} + d['askVolume1'] = {'chinese': u'卖一量', 'cellType': ""} + d['time'] = {'chinese': u'时间', 'cellType': ""} + d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + # 设置数据键 + self.setDataKey('vtSymbol') + + # 设置监控事件类型 + self.setEventType(EVENT_TICK) + + # 注册事件监听 + self.registerEvent() + + +######################################################################## +class LogMonitor(BasicMonitor): + """日志监控""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, parent=None): + """Constructor""" + super(LogMonitor, self).__init__(eventEngine, parent) + + d = OrderedDict() + d['logTime'] = {'chinese': u'时间', 'cellType': ""} + d['logContent'] = {'chinese': u'内容', 'cellType': ""} + d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + self.setEventType(EVENT_LOG) + self.registerEvent() + + + +######################################################################## +class CtaLogMonitor(BasicMonitor): + """日志监控""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, parent=None): + """Constructor""" + super(CtaLogMonitor, self).__init__(eventEngine, parent) + + d = OrderedDict() + d['logTime'] = {'chinese': u'时间', 'cellType': ""} + d['logContent'] = {'chinese': u'内容', 'cellType': ""} + # d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + self.setEventType(EVENT_CTA_LOG) + self.registerEvent() + +######################################################################## +class ErrorMonitor(BasicMonitor): + """错误监控""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, parent=None): + """Constructor""" + super(ErrorMonitor, self).__init__(eventEngine, parent) + + d = OrderedDict() + d['errorID'] = {'chinese': u'错误代码', 'cellType': ""} + d['errorMsg'] = {'chinese': u'错误信息', 'cellType': ""} + d['additionalInfo'] = {'chinese': u'补充信息', 'cellType': ""} + d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + self.setEventType(EVENT_ERROR) + self.registerEvent() + + +######################################################################## +class TradeMonitor(BasicMonitor): + """成交监控""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, parent=None): + """Constructor""" + super(TradeMonitor, self).__init__(eventEngine, parent) + + d = OrderedDict() + d['tradeID'] = {'chinese': u'成交编号', 'cellType': ""} + d['orderID'] = {'chinese': u'委托编号', 'cellType': ""} + d['symbol'] = {'chinese': u'合约代码', 'cellType': ""} + d['vtSymbol'] = {'chinese': u'名称', 'cellType': ""} + d['direction'] = {'chinese': u'方向', 'cellType': ""} + d['offset'] = {'chinese': u'开平', 'cellType': ""} + d['price'] = {'chinese': u'价格', 'cellType': ""} + d['volume'] = {'chinese': u'数量', 'cellType': ""} + d['tradeTime'] = {'chinese': u'成交时间', 'cellType': ""} + d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + self.setEventType(EVENT_TRADE) + self.registerEvent() + + +######################################################################## +class OrderMonitor(BasicMonitor): + """委托监控""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, mainEngine, parent=None): + """Constructor""" + super(OrderMonitor, self).__init__(eventEngine, parent) + + self.mainEngine = mainEngine + + d = OrderedDict() + d['orderID'] = {'chinese': u'委托编号', 'cellType': ""} + d['symbol'] = {'chinese': u'合约代码', 'cellType': ""} + d['vtSymbol'] = {'chinese': u'名称', 'cellType': ""} + d['direction'] = {'chinese': u'方向', 'cellType': ""} + d['offset'] = {'chinese': u'开平', 'cellType': ""} + d['price'] = {'chinese': u'价格', 'cellType': ""} + d['totalVolume'] = {'chinese': u'委托数量', 'cellType': ""} + d['tradedVolume'] = {'chinese': u'成交数量', 'cellType': ""} + d['status'] = {'chinese': u'状态', 'cellType': ""} + d['orderTime'] = {'chinese': u'委托时间', 'cellType': ""} + d['cancelTime'] = {'chinese': u'撤销时间', 'cellType': ""} + d['frontID'] = {'chinese': u'前置编号', 'cellType': ""} + d['sessionID'] = {'chinese': u'会话编号', 'cellType': ""} + d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + self.setDataKey('vtOrderID') + self.setEventType(EVENT_ORDER) + self.setSaveData(True) + + self.registerEvent() + + +######################################################################## +class PositionMonitor(BasicMonitor): + """持仓监控""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, parent=None): + """Constructor""" + super(PositionMonitor, self).__init__(eventEngine, parent) + + d = OrderedDict() + d['symbol'] = {'chinese': u'合约代码', 'cellType': ""} + d['vtSymbol'] = {'chinese': u'名称', 'cellType': ""} + d['direction'] = {'chinese': u'方向', 'cellType': ""} + d['position'] = {'chinese': u'持仓量', 'cellType': ""} + d['ydPosition'] = {'chinese': u'昨持仓', 'cellType': ""} + d['frozen'] = {'chinese': u'冻结量', 'cellType': ""} + d['price'] = {'chinese': u'价格', 'cellType': ""} + d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + self.setDataKey('vtPositionName') + self.setEventType(EVENT_POSITION) + self.registerEvent() + + +######################################################################## +class AccountMonitor(BasicMonitor): + """账户监控""" + + # ---------------------------------------------------------------------- + def __init__(self, eventEngine, parent=None): + """Constructor""" + super(AccountMonitor, self).__init__(eventEngine, parent) + + d = OrderedDict() + d['accountID'] = {'chinese': u'账户', 'cellType': ""} + d['preBalance'] = {'chinese': u'昨结', 'cellType': ""} + d['balance'] = {'chinese': u'净值', 'cellType': ""} + d['available'] = {'chinese': u'可用', 'cellType': ""} + d['commission'] = {'chinese': u'手续费', 'cellType': ""} + d['margin'] = {'chinese': u'保证金', 'cellType': ""} + d['closeProfit'] = {'chinese': u'平仓盈亏', 'cellType': ""} + d['positionProfit'] = {'chinese': u'持仓盈亏', 'cellType': ""} + d['gatewayName'] = {'chinese': u'接口', 'cellType': ""} + self.setHeaderDict(d) + + self.setDataKey('vtAccountID') + self.setEventType(EVENT_ACCOUNT) + self.registerEvent() diff --git a/vn.trader/utils.py b/vn.trader/utils.py new file mode 100644 index 00000000..5d4fdee4 --- /dev/null +++ b/vn.trader/utils.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# coding=utf8 +""" +上交所,市场代码 SHSE +深交所,市场代码 SZSE +中金所,市场代码 CFFEX +上期所,市场代码 SHFE +大商所,市场代码 DCE +郑商所,市场代码 CZCE +纽约商品交易所, 市场代码 CMX (GLN, SLN) +伦敦国际石油交易所, 市场代码 IPE (OIL, GAL) +纽约商业交易所, 市场代码 NYM (CON, HON) +芝加哥商品期货交易所,市场代码 CBT (SOC, SBC, SMC, CRC) +纽约期货交易所,市场代码 NYB (SGN) + +""" +from gmsdk.api import md +from vtGateway import VtTickData + +ret = md.init( + username='171322809@qq.com', + password='88888888', + mode=2 +) + +import arrow + + +def to_local(utc): + return arrow.get(utc).to('local') + + +def gm_to_vt(exchange, sym, tick): + obj = VtTickData() + + obj.symbol = sym # 合约代码 + obj.exchange = exchange # 交易所代码 + obj.vtSymbol = sym # 合约在vt系统中的唯一代码,通常是 合约代码.交易所代码 + + local_time = to_local(tick.utc_time) + # 成交数据 + obj.lastPrice = round(tick.last_price, 2) # 最新成交价 + obj.lastVolume = tick.last_volume # 最新成交量 + obj.volume = tick.cum_volume # 今天总成交量 + obj.openInterest = tick.cum_position # 持仓量 + obj.time = local_time.strftime('%H:%M:%S') # 时间 11:20:56.5 + obj.date = local_time.strftime('%Y%m%d') # 日期 20151009 + + # 常规行情 + obj.openPrice = tick.open # 今日开盘价 + obj.highPrice = tick.high # 今日最高价 + obj.lowPrice = tick.low # 今日最低价 + obj.preClosePrice = tick.pre_close + + obj.upperLimit = tick.upper_limit # 涨停价 + obj.lowerLimit = tick.lower_limit # 跌停价 + + # 一档行情 + obj.bidPrice1, obj.bidVolume1 = tick.bids[0] + + obj.askPrice1, obj.askVolume1 = tick.asks[0] + return obj + + +def get_last_n_ticks(exchange, sym, n): + ticks = md.get_last_n_ticks('%s.%s' % (exchange, sym), 10) + res = [] + for tick in ticks: + res.append(gm_to_vt(exchange, sym, tick)) + return res[::-1] + + +if __name__ == '__main__': + for tick in get_last_n_ticks('SHFE', 'ag1606', 10): + print tick.date, tick.time, tick