diff --git a/vn.strategy/README.md b/vn.archive/vn.strategy/README.md similarity index 100% rename from vn.strategy/README.md rename to vn.archive/vn.strategy/README.md diff --git a/vn.strategy/backtestingEngine.py b/vn.archive/vn.strategy/backtestingEngine.py similarity index 100% rename from vn.strategy/backtestingEngine.py rename to vn.archive/vn.strategy/backtestingEngine.py diff --git a/vn.strategy/strategyEngine.py b/vn.archive/vn.strategy/strategyEngine.py similarity index 100% rename from vn.strategy/strategyEngine.py rename to vn.archive/vn.strategy/strategyEngine.py diff --git a/vn.strategy/strategydemo/README.md b/vn.archive/vn.strategy/strategydemo/README.md similarity index 100% rename from vn.strategy/strategydemo/README.md rename to vn.archive/vn.strategy/strategydemo/README.md diff --git a/vn.strategy/strategydemo/backtestingEngine.py b/vn.archive/vn.strategy/strategydemo/backtestingEngine.py similarity index 100% rename from vn.strategy/strategydemo/backtestingEngine.py rename to vn.archive/vn.strategy/strategydemo/backtestingEngine.py diff --git a/vn.strategy/strategydemo/ctp_data_type.py b/vn.archive/vn.strategy/strategydemo/ctp_data_type.py similarity index 100% rename from vn.strategy/strategydemo/ctp_data_type.py rename to vn.archive/vn.strategy/strategydemo/ctp_data_type.py diff --git a/vn.strategy/strategydemo/demoApi.py b/vn.archive/vn.strategy/strategydemo/demoApi.py similarity index 100% rename from vn.strategy/strategydemo/demoApi.py rename to vn.archive/vn.strategy/strategydemo/demoApi.py diff --git a/vn.strategy/strategydemo/demoBacktesting.py b/vn.archive/vn.strategy/strategydemo/demoBacktesting.py similarity index 100% rename from vn.strategy/strategydemo/demoBacktesting.py rename to vn.archive/vn.strategy/strategydemo/demoBacktesting.py diff --git a/vn.strategy/strategydemo/demoEngine.py b/vn.archive/vn.strategy/strategydemo/demoEngine.py similarity index 100% rename from vn.strategy/strategydemo/demoEngine.py rename to vn.archive/vn.strategy/strategydemo/demoEngine.py diff --git a/vn.strategy/strategydemo/demoStrategy.py b/vn.archive/vn.strategy/strategydemo/demoStrategy.py similarity index 100% rename from vn.strategy/strategydemo/demoStrategy.py rename to vn.archive/vn.strategy/strategydemo/demoStrategy.py diff --git a/vn.strategy/strategydemo/eventEngine.py b/vn.archive/vn.strategy/strategydemo/eventEngine.py similarity index 100% rename from vn.strategy/strategydemo/eventEngine.py rename to vn.archive/vn.strategy/strategydemo/eventEngine.py diff --git a/vn.strategy/strategydemo/eventType.py b/vn.archive/vn.strategy/strategydemo/eventType.py similarity index 100% rename from vn.strategy/strategydemo/eventType.py rename to vn.archive/vn.strategy/strategydemo/eventType.py diff --git a/vn.strategy/strategydemo/mdconnection/empty.txt b/vn.archive/vn.strategy/strategydemo/mdconnection/empty.txt similarity index 100% rename from vn.strategy/strategydemo/mdconnection/empty.txt rename to vn.archive/vn.strategy/strategydemo/mdconnection/empty.txt diff --git a/vn.strategy/strategydemo/strategyEngine.py b/vn.archive/vn.strategy/strategydemo/strategyEngine.py similarity index 100% rename from vn.strategy/strategydemo/strategyEngine.py rename to vn.archive/vn.strategy/strategydemo/strategyEngine.py diff --git a/vn.strategy/strategydemo/tdconnection/empty.txt b/vn.archive/vn.strategy/strategydemo/tdconnection/empty.txt similarity index 100% rename from vn.strategy/strategydemo/tdconnection/empty.txt rename to vn.archive/vn.strategy/strategydemo/tdconnection/empty.txt diff --git a/vn.strategy/strategydemo/thostmduserapi.dll b/vn.archive/vn.strategy/strategydemo/thostmduserapi.dll similarity index 100% rename from vn.strategy/strategydemo/thostmduserapi.dll rename to vn.archive/vn.strategy/strategydemo/thostmduserapi.dll diff --git a/vn.strategy/strategydemo/thosttraderapi.dll b/vn.archive/vn.strategy/strategydemo/thosttraderapi.dll similarity index 100% rename from vn.strategy/strategydemo/thosttraderapi.dll rename to vn.archive/vn.strategy/strategydemo/thosttraderapi.dll diff --git a/vn.strategy/strategydemo/vnctpmd.pyd b/vn.archive/vn.strategy/strategydemo/vnctpmd.pyd similarity index 100% rename from vn.strategy/strategydemo/vnctpmd.pyd rename to vn.archive/vn.strategy/strategydemo/vnctpmd.pyd diff --git a/vn.strategy/strategydemo/vnctptd.pyd b/vn.archive/vn.strategy/strategydemo/vnctptd.pyd similarity index 100% rename from vn.strategy/strategydemo/vnctptd.pyd rename to vn.archive/vn.strategy/strategydemo/vnctptd.pyd diff --git a/vn.strategy/strategydemo/vnpy.ico b/vn.archive/vn.strategy/strategydemo/vnpy.ico similarity index 100% rename from vn.strategy/strategydemo/vnpy.ico rename to vn.archive/vn.strategy/strategydemo/vnpy.ico diff --git a/vn.oanda/README.md b/vn.oanda/README.md new file mode 100644 index 00000000..bb3cc682 --- /dev/null +++ b/vn.oanda/README.md @@ -0,0 +1,38 @@ +# vn.oanda + +### 简介 +OANDA外汇交易接口,基于REST API开发,实现了以下功能: + +1. 发送、修改、撤销委托 + +2. 查询委托、持仓(按照每笔成交算)、汇总持仓(按照单一货币对算)、资金、成交历史 + +3. 实时行情和成交推送 + +4. 获取Forex Lab中的日历、订单簿、历史持仓比、价差、交易商持仓、Autochartist + +### 特点 +相比较于[OANDA官网](http://developer.oanda.com/rest-live/sample-code/)上贴出的一些Python API(如pyoanda、oanda-trading-environment等),vn.oanda的一些不同: + +1. 面向对象的API设计,接近CTP API的结构,对于国内用户而言更容易上手 + +2. 三个独立的工作线程,分别处理:用户请求(如发送委托等)、行情推送、事件推送(如成交事件等),提供更高的性能 + +3. 参考CTP API的设计,主动函数调用的结果通过异步(回调函数)的方式推送到程序中,适用于开发真正可靠的实盘交易程序(pyoanda里使用的同步阻塞工作模式在实盘应用中的风险:想象你的交易程序发送委托请求后,因为网络问题不能立即返回,因此主线程阻塞导致界面卡死或者背后的策略引擎线程卡死,对新的行情事件完全失去响应) + +### Quick Start +1. 安装Anaconda 2.7 32位 + +2. 前往[OANDA](http://www.oanda.com)注册一个fxTrade practice测试账户(注意国家不要选中国,会无法申请API token,作者测试英国可以) + +3. 在网站登陆后,进入Manage Funds,记录下自己的Account Number + +4. 回到上一个界面,左侧有个Manage API Access(在Recent Logins上方,没有的就是第一步国家选错了),进入后生成token + +5. 下载vn.oanda到本地后,打开test.py,修改token和accountId为你的信息 + +6. 将test.py中想要测试的功能取消注释,开始使用吧! + +### API版本 +OANDA REST API + diff --git a/vn.oanda/api.py b/vn.oanda/api.py new file mode 100644 index 00000000..f982c621 --- /dev/null +++ b/vn.oanda/api.py @@ -0,0 +1,609 @@ +# encoding: utf-8 + +import json +import requests +from Queue import Queue, Empty +from threading import Thread + + +API_SETTING = {} +API_SETTING['practice'] = {'rest': 'https://api-fxpractice.oanda.com', + 'stream': 'https://stream-fxpractice.oanda.com'} +API_SETTING['trade'] = {'rest': 'https://api-fxpractice.oanda.com', + 'stream': 'https://stream-fxtrade.oanda.com/'} + + +FUNCTIONCODE_GETINSTRUMENTS = 0 +FUNCTIONCODE_GETPRICES = 1 +FUNCTIONCODE_GETPRICEHISTORY = 2 +FUNCTIONCODE_GETACCOUNTS = 3 +FUNCTIONCODE_GETACCOUNTINFO = 4 +FUNCTIONCODE_GETORDERS = 5 +FUNCTIONCODE_SENDORDER = 6 +FUNCTIONCODE_GETORDERINFO = 7 +FUNCTIONCODE_MODIFYORDER = 8 +FUNCTIONCODE_CANCELORDER = 9 +FUNCTIONCODE_GETTRADES = 10 +FUNCTIONCODE_GETTRADEINFO = 11 +FUNCTIONCODE_MODIFYTRADE= 12 +FUNCTIONCODE_CLOSETRADE = 13 +FUNCTIONCODE_GETPOSITIONS = 14 +FUNCTIONCODE_GETPOSITIONINFO= 15 +FUNCTIONCODE_CLOSEPOSITION = 16 +FUNCTIONCODE_GETTRANSACTIONS = 17 +FUNCTIONCODE_GETTRANSACTIONINFO = 18 +FUNCTIONCODE_GETACCOUNTHISTORY = 19 +FUNCTIONCODE_GETCALENDAR = 20 +FUNCTIONCODE_GETPOSITIONRATIOS = 21 +FUNCTIONCODE_GETSPREADS = 22 +FUNCTIONCODE_GETCOMMIMENTS = 23 +FUNCTIONCODE_GETORDERBOOK = 24 +FUNCTIONCODE_GETAUTOCHARTIST = 25 +FUNCTIONCODE_STREAMPRICES = 26 +FUNCTIONCODE_STREAMEVENTS = 27 + + +######################################################################## +class OandaApi(object): + """""" + DEBUG = False + + #---------------------------------------------------------------------- + def __init__(self): + """Constructor""" + self.token = '' + self.accountId = '' + self.headers = {} + self.restDomain = '' + self.streamDomain = '' + self.session = None + + self.functionSetting = {} + + self.active = False # API的工作状态 + + self.reqID = 0 # 请求编号 + self.reqQueue = Queue() # 请求队列 + self.reqThread = Thread(target=self.processQueue) # 请求处理线程 + + self.streamPricesThread = Thread(target=self.processStreamPrices) # 实时行情线程 + self.streamEventsThread = Thread(target=self.processStreamEvents) # 实时事件线程(成交等) + + #---------------------------------------------------------------------- + def init(self, settingName, token, accountId): + """初始化接口""" + self.restDomain = API_SETTING[settingName]['rest'] + self.streamDomain = API_SETTING[settingName]['stream'] + self.session = requests.Session() + + self.token = token + self.accountId = accountId + + self.headers['Authorization'] = 'Bearer ' + self.token + + self.initFunctionSetting(FUNCTIONCODE_GETINSTRUMENTS, {'path': '/v1/instruments', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETPRICES, {'path': '/v1/prices', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETPRICEHISTORY, {'path': 'v1/candles', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETACCOUNTS, {'path': '/v1/accounts', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETACCOUNTINFO, {'path': '/v1/accounts/%s' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETORDERS, {'path': '/v1/accounts/%s/orders' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_SENDORDER, {'path': '/v1/accounts/%s/orders' %self.accountId, + 'method': 'POST'}) + + self.initFunctionSetting(FUNCTIONCODE_GETORDERINFO, {'path': '/v1/accounts/%s/orders' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_MODIFYORDER, {'path': '/v1/accounts/%s/orders' %self.accountId, + 'method': 'PATCH'}) + + self.initFunctionSetting(FUNCTIONCODE_CANCELORDER, {'path': '/v1/accounts/%s/orders' %self.accountId, + 'method': 'DELETE'}) + + self.initFunctionSetting(FUNCTIONCODE_GETTRADES, {'path': '/v1/accounts/%s/trades' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETTRADEINFO, {'path': '/v1/accounts/%s/trades' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_MODIFYTRADE, {'path': '/v1/accounts/%s/trades' %self.accountId, + 'method': 'PATCH'}) + + self.initFunctionSetting(FUNCTIONCODE_CLOSETRADE, {'path': '/v1/accounts/%s/trades' %self.accountId, + 'method': 'DELETE'}) + + self.initFunctionSetting(FUNCTIONCODE_GETPOSITIONS, {'path': '/v1/accounts/%s/positions' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETPOSITIONINFO, {'path': '/v1/accounts/%s/positions' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_CLOSEPOSITION, {'path': '/v1/accounts/%s/positions' %self.accountId, + 'method': 'DELETE'}) + + self.initFunctionSetting(FUNCTIONCODE_GETTRANSACTIONS, {'path': '/v1/accounts/%s/transactions' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETTRANSACTIONINFO, {'path': '/v1/accounts/%s/transactions' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETACCOUNTHISTORY, {'path': '/v1/accounts/%s/alltransactions' %self.accountId, + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETCALENDAR, {'path': '/labs/v1/calendar', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETPOSITIONRATIOS, {'path': '/labs/v1/historical_position_ratios', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETSPREADS, {'path': '/labs/v1/spreads', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETCOMMIMENTS, {'path': '/labs/v1/commitments', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETORDERBOOK, {'path': '/labs/v1/orderbook_data', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETAUTOCHARTIST, {'path': '/labs/v1/autochartist', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_GETAUTOCHARTIST, {'path': '/labs/v1/autochartist', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_STREAMPRICES, {'path': '/v1/prices', + 'method': 'GET'}) + + self.initFunctionSetting(FUNCTIONCODE_STREAMEVENTS, {'path': '/v1/events', + 'method': 'GET'}) + + + self.active = True + self.reqThread.start() + self.streamEventsThread.start() + self.streamPricesThread.start() + + #---------------------------------------------------------------------- + def exit(self): + """退出接口""" + self.active = False + self.reqThread.join() + + #---------------------------------------------------------------------- + def initFunctionSetting(self, code, setting): + """初始化API功能字典""" + self.functionSetting[code] = setting + + #---------------------------------------------------------------------- + def processRequest(self, req): + """发送请求并通过回调函数推送数据结果""" + url = req['url'] + method = req['method'] + params = req['params'] + + stream = False + if 'stream' in req: + stream = req['stream'] + + if method in ['GET', 'DELETE']: + myreq = requests.Request(method, url, headers=self.headers, params=params) + elif method in ['POST', 'PATCH']: + myreq = requests.Request(method, url, headers=self.headers, data=params) + pre = myreq.prepare() + + r = None + error = None + + try: + r = self.session.send(pre, stream=stream) + except Exception, e: + error = e + + return r, error + + #---------------------------------------------------------------------- + def processQueue(self): + """处理请求队列中的请求""" + while self.active: + try: + req = self.reqQueue.get(block=True, timeout=1) # 获取请求的阻塞为一秒 + callback = req['callback'] + reqID = req['reqID'] + + r, error = self.processRequest(req) + + if r: + try: + data = r.json() + if self.DEBUG: + print callback.__name__ + callback(data, reqID) + except Exception, e: + self.onError(error) + else: + self.onError(error) + except Empty: + pass + + #---------------------------------------------------------------------- + def sendRequest(self, code, params, callback, optional=''): + """发送请求""" + setting = self.functionSetting[code] + + url = self.restDomain + setting['path'] + if optional: + url = url + '/' + optional + + self.reqID += 1 + + req = {'url': url, + 'method': setting['method'], + 'params': params, + 'callback': callback, + 'reqID': self.reqID} + self.reqQueue.put(req) + + return self.reqID + + #---------------------------------------------------------------------- + def onError(self, error, reqID): + """错误信息回调""" + print error, reqID + + #---------------------------------------------------------------------- + def getInstruments(self, params): + """查询可交易的合约列表""" + return self.sendRequest(FUNCTIONCODE_GETINSTRUMENTS, params, self.onGetInstruments) + + #---------------------------------------------------------------------- + def onGetInstruments(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getPrices(self, params): + """查询价格""" + return self.sendRequest(FUNCTIONCODE_GETPRICES, params, self.onGetPrices) + + #---------------------------------------------------------------------- + def onGetPrices(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getPriceHisory(self, params): + """查询历史价格数据""" + return self.sendRequest(FUNCTIONCODE_GETPRICEHISTORY, params, self.onGetPriceHistory) + + #---------------------------------------------------------------------- + def onGetPriceHistory(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getAccounts(self): + """查询用户的所有账户""" + return self.sendRequest(FUNCTIONCODE_GETACCOUNTS, {}, self.onGetAccounts) + + #---------------------------------------------------------------------- + def onGetAccounts(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getAccountInfo(self): + """查询账户数据""" + return self.sendRequest(FUNCTIONCODE_GETACCOUNTINFO, {}, self.onGetAccountInfo) + + #---------------------------------------------------------------------- + def onGetAccountInfo(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getOrders(self, params): + """查询所有委托""" + return self.sendRequest(FUNCTIONCODE_GETORDERS, params, self.onGetOrders) + + #---------------------------------------------------------------------- + def onGetOrders(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def sendOrder(self, params): + """发送委托""" + return self.sendRequest(FUNCTIONCODE_SENDORDER, params, self.onSendOrder) + + #---------------------------------------------------------------------- + def onSendOrder(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getOrderInfo(self, optional): + """查询委托信息""" + return self.sendRequest(FUNCTIONCODE_GETORDERINFO, {}, self.onGetOrderInfo, optional) + + #---------------------------------------------------------------------- + def onGetOrderInfo(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def modifyOrder(self, params, optional): + """修改委托""" + return self.sendRequest(FUNCTIONCODE_MODIFYORDER, params, self.onModifyOrder, optional) + + #---------------------------------------------------------------------- + def onModifyOrder(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def cancelOrder(self, optional): + """查询委托信息""" + return self.sendRequest(FUNCTIONCODE_CANCELORDER, {}, self.onCancelOrder, optional) + + #---------------------------------------------------------------------- + def onCancelOrder(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getTrades(self, params): + """查询所有仓位""" + return self.sendRequest(FUNCTIONCODE_GETTRADES, params, self.onGetTrades) + + #---------------------------------------------------------------------- + def onGetTrades(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getTradeInfo(self, optional): + """查询仓位信息""" + return self.sendRequest(FUNCTIONCODE_GETTRADEINFO, {}, self.onGetTradeInfo, optional) + + #---------------------------------------------------------------------- + def onGetTradeInfo(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def modifyTrade(self, params, optional): + """修改仓位""" + return self.sendRequest(FUNCTIONCODE_MODIFYTRADE, params, self.onModifyTrade, optional) + + #---------------------------------------------------------------------- + def onModifyTrade(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def closeTrade(self, optional): + """平仓""" + return self.sendRequest(FUNCTIONCODE_CLOSETRADE, {}, self.onCloseTrade, optional) + + #---------------------------------------------------------------------- + def onCloseTrade(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getPositions(self): + """查询所有汇总仓位""" + return self.sendRequest(FUNCTIONCODE_GETPOSITIONS, {}, self.onGetPositions) + + #---------------------------------------------------------------------- + def onGetPositions(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getPositionInfo(self, optional): + """查询汇总仓位信息""" + return self.sendRequest(FUNCTIONCODE_GETPOSITIONINFO, {}, self.onGetPositionInfo, optional) + + #---------------------------------------------------------------------- + def onGetPositionInfo(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def closePosition(self, optional): + """平仓汇总仓位信息""" + return self.sendRequest(FUNCTIONCODE_CLOSEPOSITION, {}, self.onClosePosition, optional) + + #---------------------------------------------------------------------- + def onClosePosition(self, data, reqID): + """回调函数""" + print data, reqID + + + #---------------------------------------------------------------------- + def getTransactions(self, params): + """查询所有资金变动""" + return self.sendRequest(FUNCTIONCODE_GETTRANSACTIONS, params, self.onGetTransactions) + + #---------------------------------------------------------------------- + def onGetTransactions(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getTransactionInfo(self, optional): + """查询资金变动信息""" + return self.sendRequest(FUNCTIONCODE_GETTRANSACTIONINFO, {}, self.onGetTransactionInfo, optional) + + #---------------------------------------------------------------------- + def onGetTransactionInfo(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getAccountHistory(self): + """查询账户资金变动历史""" + return self.sendRequest(FUNCTIONCODE_GETACCOUNTHISTORY, {}, self.onGetAccountHistory) + + #---------------------------------------------------------------------- + def onGetAccountHistory(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getCalendar(self, params): + """查询日历""" + return self.sendRequest(FUNCTIONCODE_GETCALENDAR, params, self.onGetCalendar) + + #---------------------------------------------------------------------- + def onGetCalendar(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getPositionRatios(self, params): + """查询持仓比例""" + return self.sendRequest(FUNCTIONCODE_GETPOSITIONRATIOS, params, self.onGetPositionRatios) + + #---------------------------------------------------------------------- + def onGetPositionRatios(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getSpreads(self, params): + """查询所有仓位""" + return self.sendRequest(FUNCTIONCODE_GETSPREADS, params, self.onGetSpreads) + + #---------------------------------------------------------------------- + def onGetSpreads(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getCommitments(self, params): + """查询交易商持仓情况""" + return self.sendRequest(FUNCTIONCODE_GETCOMMIMENTS, params, self.onGetCommitments) + + #---------------------------------------------------------------------- + def onGetCommitments(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getOrderbook(self, params): + """查询订单簿""" + return self.sendRequest(FUNCTIONCODE_GETORDERBOOK, params, self.onGetOrderbook) + + #---------------------------------------------------------------------- + def onGetOrderbook(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def getAutochartist(self, params): + """查询Autochartist识别的模式""" + return self.sendRequest(FUNCTIONCODE_GETAUTOCHARTIST, params, self.onGetAutochartist) + + #---------------------------------------------------------------------- + def onGetAutochartist(self, data, reqID): + """回调函数""" + print data, reqID + + #---------------------------------------------------------------------- + def onPrice(self, data): + """行情推送""" + print data + + #---------------------------------------------------------------------- + def onEvent(self, data): + """事件推送(成交等)""" + print data + + #---------------------------------------------------------------------- + def processStreamPrices(self): + """获取价格推送""" + # 首先获取所有合约的代码 + setting = self.functionSetting[FUNCTIONCODE_GETINSTRUMENTS] + req = {'url': self.restDomain + setting['path'], + 'method': setting['method'], + 'params': {'accountId': self.accountId}} + r, error = self.processRequest(req) + if r: + try: + data = r.json() + symbols = [d['instrument'] for d in data['instruments']] + except Exception, e: + self.onError(e, -1) + return + else: + self.onError(error, -1) + return + + # 然后订阅所有的合约行情 + setting = self.functionSetting[FUNCTIONCODE_STREAMPRICES] + params = {'accountId': self.accountId, + 'instruments': ','.join(symbols)} + req = {'url': self.streamDomain + setting['path'], + 'method': setting['method'], + 'params': params, + 'stream': True} + r, error = self.processRequest(req) + + if r: + for line in r.iter_lines(): + if line: + try: + msg = json.loads(line) + + if self.DEBUG: + print self.onPrice.__name__ + + self.onPrice(msg) + except Exception, e: + self.onError(e, -1) + + if not self.active: + break + else: + self.onError(error, -1) + + #---------------------------------------------------------------------- + def processStreamEvents(self): + """获取事件推送""" + setting = self.functionSetting[FUNCTIONCODE_STREAMEVENTS] + req = {'url': self.streamDomain + setting['path'], + 'method': setting['method'], + 'params': {}, + 'stream': True} + r, error = self.processRequest(req) + if r: + + for line in r.iter_lines(): + if line: + try: + msg = json.loads(line) + + if self.DEBUG: + print self.onEvent.__name__ + + self.onEvent(msg) + except Exception, e: + self.onError(e, -1) + + if not self.active: + break + else: + self.onError(error, -1) \ No newline at end of file diff --git a/vn.oanda/test.py b/vn.oanda/test.py new file mode 100644 index 00000000..4031a0aa --- /dev/null +++ b/vn.oanda/test.py @@ -0,0 +1,105 @@ +# encoding: utf-8 + +from api import OandaApi + + +if __name__ == '__main__': + token = '' + accountId = '' + + api = OandaApi() + api.DEBUG = True + + api.init('practice', token, accountId) + + # 获取交易合约列表,通过 + #api.getInstruments({'accountId': accountId}) + + # 获取价格,通过 + #api.getPrices({'instruments': 'EUR_USD'}) + + # 获取历史数据,失败 + #api.getPriceHisory({'instruments': 'EUR_USD', + #'granularity': 'D', + #'candleFormat': 'midpoint', + #'count': '50'}) + + # 查询用户的所有账户,通过 + #api.getAccounts() + + # 查询账户信息,通过 + #api.getAccountInfo() + + # 查询委托数据,通过 + #api.getOrders({}) + + # 发送委托,通过 + #api.sendOrder({'instrument': 'EUR_USD', + #'units': '10000', + #'side': 'buy', + #'type': 'market'}) + + # 查询委托数据,通过 + #api.getOrderInfo('123') + + # 修改委托,通过 + #api.modifyOrder({'units': '10000', + #'side': 'buy', + #'type': 'market'}, '123') + + # 撤销委托,通过 + #api.cancelOrder('123') + + # 查询所有持仓,通过 + #api.getTrades({}) + + # 查询持仓数据,通过 + #api.getTradeInfo('10125150909') + + # 修改持仓,通过 + #api.modifyTrade({'trailingStop': '150'}, '10125150909') + + # 平仓,通过 + #api.closeTrade('10125150909') + + # 查询汇总持仓,通过 + #api.getPositions() + + # 查询汇总持仓细节,通过 + #api.getPositionInfo('EUR_USD') + + # 平仓汇总持仓,通过 + #api.closePosition('EUR_USD') + + # 查询账户资金变动,通过 + #api.getTransactions({}) + + # 查询资金变动信息,通过 + #api.getTransactionInfo('10135713982') + + # 查询账户变动历史,部分通过,某些情况下可能触发JSONDecodeError + #api.getAccountHistory() + + # 查询财经日历,通过 + #api.getCalendar({'period': '604800'}) + + # 查询历史持仓比,通过 + #api.getPositionRatios({'instrument': 'EUR_USD', + #'period': '604800'}) + + # 查询历史价差,通过 + #api.getSpreads({'instrument': 'EUR_USD', + #'period': '604800'}) + + # 查询交易商持仓,通过 + #api.getCommitments({'instrument': 'EUR_USD'}) + + # 查询订单簿,通过 + #api.getOrderbook({'instrument': 'EUR_USD', + #'period': '604800'}) + + # 查询Autochartist,失败,OANDA服务器报错 + #api.getAutochartist({'instrument': 'EUR_USD'}) + + # 阻塞 + input() \ No newline at end of file