from datetime import datetime
from threading import Thread
import time
import sys
from ibapi.client import EClient, Contract
from ibapi.order import Order
from ibapi.wrapper import EWrapper
from ibapi.utils import iswrapper
from ibapi.scanner import ScannerSubscription
from ibapi.tag_value import TagValue
import pandas as pd
import numpy as np
class SimpleStrategy(EWrapper, EClient):
''' Serves as the client and the wrapper '''
def __init__(self, addr, port, client_id):
EWrapper.__init__(self)
EClient.__init__(self, self)
# 订单号
self.order_id = 0
# 初始化账户
self.funds = 0.0
# 保存价格
self.price_list=[]
# 保存仓位
self.position_size = 0.0
self.avg_cost = 0.0
# 连接到TWS
self.connect(addr, port, client_id)
thread = Thread(target=self.run)
thread.start()
@iswrapper
def currentTime(self, cur_time):
t = datetime.fromtimestamp(cur_time)
print('Current time: {}'.format(t))
@iswrapper
def scannerData(self, reqId: int, rank: int, contractDetails,
distance: str, benchmark: str, projection: str, legsStr: str):
# 处理市场扫描仪数据
super().scannerData(reqId, rank, contractDetails, distance, benchmark,
projection, legsStr)
print("ScannerData. ReqId:", reqId, "Rank:", rank, "Symbol:", contractDetails.contract.symbol,
"SecType:", contractDetails.contract.secType,
"Currency:", contractDetails.contract.currency,
"Distance:", distance, "Benchmark:", benchmark,
"Projection:", projection, "Legs String:", legsStr)
# print("ScannerData. ReqId:", reqId, ScanData(contractDetails.contract, rank, distance, benchmark, projection, legsStr))
@iswrapper
def scannerDataEnd(self, reqId: int):
# 市场扫描仪获取数据结束
super().scannerDataEnd(reqId)
print("ScannerDataEnd. ReqId:", reqId)
@iswrapper
def scannerParameters(self, xml: str):
# 处理获取市场扫描仪的参数
super().scannerParameters(xml)
# df = pd.read_xml(xml)
# print(df)
# df.to_csv("scanner.csv")
open('scanner.txt', 'w',encoding="utf-8").write(xml)
print("ScannerParameters received.")
@iswrapper
def contractDetails(self, reqId, details):
print('Long name: {}'.format(details.longName))
print('Category: {}'.format(details.category))
print('Subcategory: {}'.format(details.subcategory))
print('Contract ID: {}\n'.format(details.contract.conId))
@iswrapper
def contractDetailsEnd(self, reqId):
print('The End')
@iswrapper
def nextValidId(self, order_id):
''' Provides the next order ID '''
self.order_id = order_id print('Order ID: {}'.format(order_id))
@iswrapper
def openOrder(self,order_id, contract, order, state):
''' Called in response to the submitted order '''
print('Order status: '.format(state.status))
print('Commission charged: '.format(state.commission))
@iswrapper
def orderStatus(self,order_id, status, filled, remaining, avgFillPrice, \
permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice):
''' Check the status of the subnitted order '''
print('Number of filled positions: {}'.format(filled))
print('Average fill price: {}'.format(avgFillPrice))
@iswrapper
def position(self, account: str, contract: Contract, position,
avgCost: float):
super().position(account, contract, position, avgCost)
print("Position.", "Account:", account, "Symbol:", contract.symbol, "SecType:",
contract.secType, "Currency:", contract.currency,
"Position:", position, "Avg cost:", avgCost)
if contract.symbol=="EUR" and contract.secType=="CASH" and contract.currency=="USD":
self.position_size = float(position)
self.avg_cost = avgCost @iswrapper
def positionEnd(self):
super().positionEnd()
print("PositionEnd")
@iswrapper
def accountSummary(self, req_id, account, tag, value, currency):
''' Read information about the account '''
print('req_id : {} Account {}: {} = {}, currency = {}'.format(req_id, account, tag, value , currency))
if tag == 'AvailableFunds':
print('Account {}: available funds = {}'.format(account, value))
self.funds = float(value)
@iswrapper
def tickByTickMidPoint(self, reqId: int, time: int, midPoint: float):
super().tickByTickMidPoint(reqId, time, midPoint)
print("Midpoint. ReqId:", reqId,"Time:", datetime.fromtimestamp(time),"MidPoint:", midPoint)
@iswrapper
def tickByTickBidAsk(self, reqId: int, time: int, bidPrice: float, askPrice: float, bidSize, askSize, tickAttribBidAsk):
super().tickByTickBidAsk(reqId, time, bidPrice, askPrice, bidSize,askSize, tickAttribBidAsk)
print("BidAsk. ReqId:", reqId,"Time:", datetime.fromtimestamp(time),
"BidPrice:", bidPrice, "AskPrice:", askPrice, "BidSize:", bidSize,"AskSize:", askSize, "BidPastLow:",
tickAttribBidAsk.bidPastLow,"AskPastHigh:", tickAttribBidAsk.askPastHigh)
@iswrapper
def tickByTickAllLast(self, reqId: int, tickType: int, time: int, price: float,
size, tickAtrribLast, exchange: str,specialConditions: str):
super().tickByTickAllLast(reqId, tickType, time, price, size, tickAtrribLast,
exchange, specialConditions)
if tickType == 1:
print("Last.", end='')
else:
print("AllLast.", end='')
print(" ReqId:", reqId,
"Time:", datetime.fromtimestamp(time),
"Price:", price, "Size:", size, "Exch:" , exchange,
"Spec Cond:", specialConditions, "PastLimit:", tickAtrribLast.pastLimit,
"Unreported:",tickAtrribLast.unreported)
@iswrapper
def tickPrice(self, reqId, tickType, price: float,attrib):
super().tickPrice(reqId, tickType, price, attrib)
print("TickPrice. TickerId:", reqId, "tickType:", tickType,
"Price:", price, "CanAutoExecute:", attrib.canAutoExecute,
"PastLimit:", attrib.pastLimit, end=' ')
@iswrapper
def tickSize(self, reqId, tickType, size):
super().tickSize(reqId, tickType, size)
print("TickSize. TickerId:", reqId, "TickType:", tickType, "Size: ", size)
@iswrapper
def tickGeneric(self, reqId, tickType, value: float):
super().tickGeneric(reqId, tickType, value)
print("TickGeneric. TickerId:", reqId, "TickType:", tickType, "Value:", value)
@iswrapper
def realtimeBar(self, reqId, time, open, high, low, close, volume, WAP, count):
''' Called in response to reqRealTimeBars '''
print('realtimeBar:{},time:{} - Opening : {},high :{},low :{},close :{},volume :{},WAP :{},count :{}'.format(reqId,datetime.fromtimestamp(time),open,high,low,close,volume,WAP,count))
self.price_list.append(close)
@iswrapper
def historicalData(self, reqId:int, bar):
print("HistoricalData. ReqId:", reqId, "BarData.", bar)
@iswrapper
def historicalDataEnd(self, reqId: int, start: str, end: str):
super().historicalDataEnd(reqId, start, end)
print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)
@iswrapper
def historicalDataUpdate(self, reqId: int, bar):
print("HistoricalDataUpdate. ReqId:", reqId, "BarData.", bar)
@iswrapper
def histogramData(self, reqId:int, items):
print("HistogramData. ReqId:", reqId, "HistogramDataList:", "[%s]" % "; ".join(map(str, items)))
@iswrapper
def historicalTicks(self, reqId: int, ticks, done: bool):
for tick in ticks:
print("HistoricalTick. ReqId:", reqId, tick)
@iswrapper
def historicalTicksBidAsk(self, reqId: int, ticks,done: bool):
for tick in ticks:
print("HistoricalTickBidAsk. ReqId:", reqId, tick)
@iswrapper
def historicalTicksLast(self, reqId: int, ticks,done: bool):
for tick in ticks:
print("HistoricalTickLast. ReqId:", reqId, tick)
@iswrapper
def fundamentalData(self, reqId, data):
''' Called in response to reqFundamentalData '''
print('Fundamental data: ' + data)
@iswrapper
def error(self, req_id, code, msg):
print('Error {}: {}'.format(code, msg))
def main():
# Create the client and connect to TWS
client = SimpleStrategy('127.0.0.1', 7497, 0)
client.reqCurrentTime()
# Sleep while the request is processed
time.sleep(0.5)
# client.reqContractDetails(1, contract)
# print("self.conn",client.conn)
# print("self.isConnected()",client.isConnected())
time.sleep(2)
# # 设置一个限价单
# order = Order()
# order.action = 'SELL'
# order.totalQuantity = 20000
# order.orderType = 'MKT'
# # 给order获取一个有效的id
# client.reqIds(1)
# time.sleep(0.5)
# # 下单
# client.placeOrder(order_id, contract, order)
# # 获取持仓的信息
# client.reqPositions()
# time.sleep(2)
# # 获取账户的信息
# client.reqAccountSummary(0, 'All', 'AccountType,AvailableFunds')
# time.sleep(2)
# 请求tick数据
# print("获取bidask的数据")
# client.reqTickByTickData(1, contract, 'BidAsk', 1, True)
# time.sleep(5)
# print("获取last的数据")
# client.reqTickByTickData(2, contract, 'Last', 1, False)
# time.sleep(5)
# print("获取alllast的数据")
# client.reqTickByTickData(3, contract, 'AllLast', 1, True)
# time.sleep(10)
# print("获取midpoint的数据")
# client.reqTickByTickData(0, contract, 'MidPoint', 1, True)
# time.sleep(5)
# 请求市场数据
# client.reqMktData(4, contract, '', False, False, [])
# 请求bar数据
# client.reqRealTimeBars(5, contract, 10, 'MIDPOINT', True, [])
# 请求历史数据
# now = datetime.now().strftime("%Y%m%d, %H:%M:%S")
# client.reqHistoricalData(6, contract, now, '2 w', '1 day',
# 'MIDPOINT', False, 1, False, [])
# 请求历史直方图数据
# client.reqHistogramData(7,contract,1,"3 days")
# 请求历史tick数据
# client.reqHistoricalTicks(8,contract,"20211230 21:39:33", "", 10, "TRADES", 1, True, [])
# 请求基础数据
# con = Contract()
# con.symbol = 'IBM'
# con.secType = 'STK'
# con.exchange = 'SMART'
# con.currency = 'USD'
# client.reqFundamentalData(9, con, 'ReportSnapshot', [])
# # 创建一个市场扫描仪
# ss = ScannerSubscription()
# ss.instrument = 'STK'
# ss.locationCode = 'STK.US.MAJOR'
# ss.scanCode = 'HOT_BY_VOLUME'
# # 增加额外的筛选标准
# tagvalues = []
# tagvalues.append(TagValue('avgVolumeAbove', '500000'))
# tagvalues.append(TagValue('marketCapAbove1e6', '10'))
# # 请求过滤后的contract
# client.reqScannerSubscription(0, ss, [], tagvalues)
# # 请求市场扫描仪的过滤参数
# # client.reqScannerParameters()
# 写一个简单的策略,当持仓为0的时候,当价格大于20周期的5秒钟的均线的时候,开多;持仓大于0的时候,当价格小于20周期的5秒钟的均线的时候平多
# 设置交易的contract
contract = Contract()
contract.symbol = "EUR"
contract.secType = "CASH"
contract.currency = "USD"
contract.exchange = "IDEALPRO"
# 设置一个买入市价单
buy_order = Order()
buy_order.action = 'BUY'
buy_order.totalQuantity = 20000
buy_order.orderType = 'MKT'
# 设置一个卖出市价单
sell_order = Order()
sell_order.action = 'SELL'
sell_order.totalQuantity = 20000
sell_order.orderType = 'MKT'
client.reqRealTimeBars(5, contract, 10, 'MIDPOINT', True, [])
# 获取账户持仓
client.reqPositions()
time.sleep(1)
# 获取账户的信息
client.reqAccountSummary(0, 'All', 'AccountType,AvailableFunds')
time.sleep(1)
# 设置运行1000个bar
count = 1000
pre_bar_num = len(client.price_list)
while count>0:
now_bar_num = len(client.price_list)
client.reqCurrentTime()
if now_bar_num>=5 and now_bar_num > pre_bar_num:
count = count-1
now_price = client.price_list[-1]
now_avg_price = sum(client.price_list[-5:])/5
if client.position_size<=0 and now_price>now_avg_price:
print('now_price',now_price,"now_avg_price",now_avg_price)
print("当前账户持仓",client.position_size,"当前bar数目",now_bar_num,"前一个bar数目",pre_bar_num,"count",count)
print("此时应该平空开多")
client.reqIds(1)
client.placeOrder(client.order_id,contract,buy_order)
print("下多单成功")
if client.position_size>0 and now_price<now_avg_price:
print('now_price',now_price,"now_avg_price",now_avg_price)
print("当前账户持仓",client.position_size,"当前bar数目",now_bar_num,"前一个bar数目",pre_bar_num,"count",count)
print("此时应该平空开多")
client.reqIds(1)
client.placeOrder(client.order_id,contract,sell_order)
print("下空单成功")
pre_bar_num = now_bar_num
time.sleep(1)
# # 休息5秒钟,等待数据返回
# time.sleep(5)
# 断开连接
client.disconnect()
if __name__ == '__main__':
main()
盈透证券(IB) TWS API使用教程(python版本)及一个简单的程序化交易策略
作者:yunjinqi
类别:教程
日期:2022-01-03 21:16:04
阅读:3951 次
消耗积分:0 分
版权所有,转载本站文章请注明出处:云子量化, https://www.yunjinqi.top/article/66
最新文章
系统当前共有 469 篇文章