© Ran Aroussi
@aroussi | aroussi.com | github.com/ranaroussi
August, 2017
(live example to follow)
import quandl
# quandl.ApiConfig.api_key = "YOUR_KEY_HERE"
df = quandl.get('WIKI/AAPL')
df.tail()
Open | High | Low | Close | Volume | Ex-Dividend | Split Ratio | Adj. Open | Adj. High | Adj. Low | Adj. Close | Adj. Volume | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | ||||||||||||
2017-08-17 | 160.52 | 160.71 | 157.8400 | 157.87 | 26925694.0 | 0.0 | 1.0 | 160.52 | 160.71 | 157.8400 | 157.87 | 26925694.0 |
2017-08-18 | 157.86 | 159.50 | 156.7200 | 157.50 | 27012525.0 | 0.0 | 1.0 | 157.86 | 159.50 | 156.7200 | 157.50 | 27012525.0 |
2017-08-21 | 157.50 | 157.89 | 155.1101 | 157.21 | 26145653.0 | 0.0 | 1.0 | 157.50 | 157.89 | 155.1101 | 157.21 | 26145653.0 |
2017-08-22 | 158.23 | 160.00 | 158.0200 | 159.78 | 21297812.0 | 0.0 | 1.0 | 158.23 | 160.00 | 158.0200 | 159.78 | 21297812.0 |
2017-08-23 | 159.07 | 160.47 | 158.8800 | 159.98 | 19198189.0 | 0.0 | 1.0 | 159.07 | 160.47 | 158.8800 | 159.98 | 19198189.0 |
df = quandl.get('CHRIS/CME_CL1')
df.tail()
# see more python methods @ quandl.com/tools/python
# Useful databases:
# - https://www.quandl.com/data/WIKI-Wiki-EOD-Stock-Prices
# - https://www.quandl.com/data/CHRIS-Wiki-Continuous-Futures
Open | High | Low | Last | Change | Settle | Volume | Previous Day Open Interest | |
---|---|---|---|---|---|---|---|---|
Date | ||||||||
2017-08-17 | 46.80 | 47.19 | 46.46 | 46.93 | 0.31 | 47.09 | 596093.0 | 161590.0 |
2017-08-18 | 46.93 | 48.74 | 46.78 | 48.73 | 1.42 | 48.51 | 247019.0 | 96943.0 |
2017-08-21 | 48.72 | 48.75 | 47.03 | 47.40 | 1.14 | 47.37 | 124355.0 | 62446.0 |
2017-08-22 | 47.45 | 48.03 | 47.20 | 47.65 | 0.27 | 47.64 | 28373.0 | 25636.0 |
2017-08-23 | 47.64 | 48.50 | 47.53 | 48.37 | 0.58 | 48.41 | 700754.0 | 522164.0 |
(Sadly, this service became very unreliable in terms of availability)
from pandas_datareader import data as pdr
df = pdr.get_data_yahoo("AAPL", start="2010-01-01")
df.tail()
Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
2017-08-18 | 157.860001 | 159.500000 | 156.720001 | 157.500000 | 157.500000 | 27428100 |
2017-08-21 | 157.500000 | 157.889999 | 155.110001 | 157.210007 | 157.210007 | 26368500 |
2017-08-22 | 158.229996 | 160.000000 | 158.020004 | 159.779999 | 159.779999 | 21604600 |
2017-08-23 | 159.070007 | 160.470001 | 158.880005 | 159.979996 | 159.979996 | 19284400 |
2017-08-24 | 160.429993 | 160.740005 | 158.550003 | 159.039993 | 159.039993 | 9437854 |
# read csv from eoddata.com
df = pd.read_csv('./AAPL_20170102_20170823.csv')
df.tail()
Symbol | Date | Open | High | Low | Close | Volume | |
---|---|---|---|---|---|---|---|
163 | AAPL | 17-Aug-2017 | 160.52 | 160.71 | 157.84 | 157.86 | 27940500 |
164 | AAPL | 18-Aug-2017 | 157.86 | 159.50 | 156.72 | 157.50 | 27428000 |
165 | AAPL | 21-Aug-2017 | 157.50 | 157.89 | 155.11 | 157.21 | 26368500 |
166 | AAPL | 22-Aug-2017 | 158.23 | 160.00 | 158.02 | 159.78 | 21604500 |
167 | AAPL | 23-Aug-2017 | 159.07 | 160.47 | 158.88 | 159.98 | 19399000 |
# parse date column and set as index while reading
df = pd.read_csv('./AAPL_20170102_20170823.csv',
parse_dates=['Date'], index_col=['Date'])
df.tail()
Symbol | Open | High | Low | Close | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
2017-08-17 | AAPL | 160.52 | 160.71 | 157.84 | 157.86 | 27940500 |
2017-08-18 | AAPL | 157.86 | 159.50 | 156.72 | 157.50 | 27428000 |
2017-08-21 | AAPL | 157.50 | 157.89 | 155.11 | 157.21 | 26368500 |
2017-08-22 | AAPL | 158.23 | 160.00 | 158.02 | 159.78 | 21604500 |
2017-08-23 | AAPL | 159.07 | 160.47 | 158.88 | 159.98 | 19399000 |
api_token, account_id = open('./oanda.conf').read().split(',')
import oandapy
oanda = oandapy.API(environment="practice", access_token=api_token)
data = oanda.get_history(instrument="EUR_USD",
granularity='D',
start='2017-01-01')
# convert candles to dataframe
df = pd.DataFrame(data['candles'])
df.set_index('time', inplace=True)
df.index = pd.to_datetime(df.index)
df.tail()
closeAsk | closeBid | complete | highAsk | highBid | lowAsk | lowBid | openAsk | openBid | volume | |
---|---|---|---|---|---|---|---|---|---|---|
time | ||||||||||
2017-08-17 21:00:00 | 1.17633 | 1.17581 | True | 1.17758 | 1.17741 | 1.17095 | 1.17079 | 1.17235 | 1.17203 | 58908 |
2017-08-20 21:00:00 | 1.18157 | 1.18135 | True | 1.18286 | 1.18273 | 1.17325 | 1.17313 | 1.17600 | 1.17500 | 32658 |
2017-08-21 21:00:00 | 1.17627 | 1.17603 | True | 1.18251 | 1.18237 | 1.17461 | 1.17447 | 1.18175 | 1.18139 | 36071 |
2017-08-22 21:00:00 | 1.18082 | 1.18060 | True | 1.18239 | 1.18226 | 1.17412 | 1.17393 | 1.17627 | 1.17599 | 39235 |
2017-08-23 21:00:00 | 1.18063 | 1.18050 | False | 1.18190 | 1.18175 | 1.17849 | 1.17836 | 1.18105 | 1.18072 | 27493 |
reqs = 0
while True:
price = oanda.get_prices(instruments="EUR_USD")
print(price) # price available via price['prices'][0]
reqs += 1
if (reqs == 5):
break
time.sleep(1)
{'prices': [{'instrument': 'EUR_USD', 'time': '2017-08-24T15:46:16.172298Z', 'bid': 1.18053, 'ask': 1.18065}]} {'prices': [{'instrument': 'EUR_USD', 'time': '2017-08-24T15:46:16.172298Z', 'bid': 1.18053, 'ask': 1.18065}]} {'prices': [{'instrument': 'EUR_USD', 'time': '2017-08-24T15:46:16.172298Z', 'bid': 1.18053, 'ask': 1.18065}]} {'prices': [{'instrument': 'EUR_USD', 'time': '2017-08-24T15:46:16.172298Z', 'bid': 1.18053, 'ask': 1.18065}]} {'prices': [{'instrument': 'EUR_USD', 'time': '2017-08-24T15:46:24.734534Z', 'bid': 1.18049, 'ask': 1.18061}]}
Before anything...
import ezibpy
import time
# initialize ezIBpy
ibConn = ezibpy.ezIBpy()
# create callback method
completed = False
def ibCallback(caller, msg, **kwargs):
global completed
if caller == "handleHistoricalData":
completed = kwargs['completed']
# connect to TWS
ibConn.connect(port=4001)
ibConn.ibCallback = ibCallback
# create a contract
contract = ibConn.createStockContract("AAPL")
# request historical data
ibConn.requestHistoricalData(resolution="1 day", lookback="1 Y")
# wait until data is downloaded
while not completed:
time.sleep(1)
# if we got here, download is completed
print("download completed")
# cancel request and disconnect from TWS
ibConn.cancelHistoricalData(contract)
ibConn.disconnect()
Server Version: 76 TWS Time at connection:20170824 18:48:42 IST
download completed
# access historica data
df = ibConn.historicalData['AAPL']
df.tail()
C | H | L | O | OI | V | WAP | |
---|---|---|---|---|---|---|---|
datetime | |||||||
2017-08-20 | 154.89 | 162.13 | 152.69 | 158.73 | 152116 | 180035 | 157.1500 |
2017-08-21 | 156.09 | 161.01 | 151.88 | 154.80 | 152570 | 181123 | 155.0460 |
2017-08-22 | 157.77 | 162.28 | 153.72 | 156.13 | 152129 | 180130 | 158.0560 |
2017-08-23 | 156.50 | 163.15 | 153.84 | 157.73 | 152233 | 180199 | 157.1290 |
2017-08-24 | 156.99 | 161.44 | 154.08 | 156.58 | 74676 | 88752 | 156.8995 |
# create streamer
class OandaBasicStreamer(oandapy.Streamer):
def __init__(self, *args, **kwargs):
oandapy.Streamer.__init__(self, *args, **kwargs)
self.ticks = 0
def stream(self, account_id, symbols):
oandapy.Streamer.start(self,
accountId=account_id,
instruments=symbols
)
def on_error(self, data):
self.disconnect()
# logic goes here:
def on_success(self, data):
if 'tick' in data:
self.ticks += 1
print(data)
stream = OandaBasicStreamer(environment="practice", access_token=api_token)
try:
stream.rates(account_id, instruments="EUR_USD")
except (KeyboardInterrupt, SystemExit):
print('Stopped by user...')
{'tick': {'instrument': 'EUR_USD', 'time': '2017-08-24T15:47:54.821310Z', 'bid': 1.18048, 'ask': 1.1806}} {'tick': {'instrument': 'EUR_USD', 'time': '2017-08-24T15:47:58.643527Z', 'bid': 1.18043, 'ask': 1.18056}} {'tick': {'instrument': 'EUR_USD', 'time': '2017-08-24T15:48:01.889783Z', 'bid': 1.18039, 'ask': 1.18052}} {'tick': {'instrument': 'EUR_USD', 'time': '2017-08-24T15:48:01.922014Z', 'bid': 1.18039, 'ask': 1.18051}} {'tick': {'instrument': 'EUR_USD', 'time': '2017-08-24T15:48:03.111637Z', 'bid': 1.18042, 'ask': 1.18054}} Stopped by user...
import plotly.plotly as ply
import plotly.graph_objs as pgo
import plotly.tools as tls
stream_ids = tls.get_credentials_file()['stream_ids']
def init_plotly_streaming_chart(token, maxpoints=100,
title="Untitled", auto_open=False):
# create a new streaming chart
stream = pgo.Stream(
token=token,
maxpoints=maxpoints
)
# initialize streaming chart
tracer = pgo.Scatter(x=[], y=[], stream=stream)
figure = pgo.Figure(data=pgo.Data([tracer]),
layout=pgo.Layout(title=title))
return ply.plot(figure, auto_open=auto_open)
chart_url = init_plotly_streaming_chart(
token=stream_ids[0],
maxpoints=50,
title="Oanda Streaming Demo")
print(chart_url)
https://plot.ly/~ranaroussi/132
# create streamer
class OandaPlotter(OandaBasicStreamer):
# logic goes here:
def on_success(self, data):
if 'tick' in data:
midprice = (data['tick']['bid'] + data['tick']['ask']) / 2
streamer.write(dict(x=self.ticks, y=midprice))
self.ticks += 1
tls.embed(chart_url)
stream = OandaPlotter(environment="practice", access_token=api_token)
streamer = ply.Stream(stream_ids[0])
streamer.open()
try:
stream.rates(account_id, instruments="EUR_USD")
except (KeyboardInterrupt, SystemExit):
print('Stopped by user...')
streamer.close()
Stopped by user...
import ezibpy
import time
# initialize ezIBpy
ibConn = ezibpy.ezIBpy()
# create callback method
def ibCallback(caller, msg, **kwargs):
if "tick" in kwargs:
tick = ibConn.marketData[msg.tickerId]
tick['datetime'] = tick.index
print(tick.to_dict(orient='records')[0])
# connect to TWS
ibConn.connect(port=4001)
ibConn.ibCallback = ibCallback
Server Version: 76 TWS Time at connection:20170824 18:50:23 IST
# create a contract
contract = ibConn.createFuturesContract("ES",
exchange="GLOBEX", expiry="201709")
# request market data for the contract
ibConn.requestMarketData()
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
print('Stopped by user...')
# cancel request and disconnect from TWS
ibConn.cancelMarketData(contract)
ibConn.disconnect()
{'ask': 2424.75, 'asksize': 432, 'bid': 2424.5, 'bidsize': 410, 'last': 2424.75, 'lastsize': 2, 'volume': 805304, 'datetime': '2017-08-24 18:50:27.000000'} {'ask': 48.25, 'asksize': 4, 'bid': 48.23, 'bidsize': 2, 'last': 48.23, 'lastsize': 5, 'volume': 236484, 'datetime': '2017-08-24 18:50:27.000000'} {'ask': 2424.75, 'asksize': 432, 'bid': 2424.5, 'bidsize': 410, 'last': 2424.75, 'lastsize': 2, 'volume': 805304, 'datetime': '2017-08-24 18:50:27.000000'} {'ask': 48.25, 'asksize': 124, 'bid': 48.23, 'bidsize': 92, 'last': 48.23, 'lastsize': 5, 'volume': 236484, 'datetime': '2017-08-24 18:50:27.000000'} {'ask': 2424.75, 'asksize': 176, 'bid': 2424.5, 'bidsize': 176, 'last': 2424.75, 'lastsize': 88, 'volume': 805304, 'datetime': '2017-08-24 18:50:28.000000'} {'ask': 48.25, 'asksize': 124, 'bid': 48.23, 'bidsize': 92, 'last': 48.24, 'lastsize': 1, 'volume': 236484, 'datetime': '2017-08-24 18:50:30.000000'} Stopped by user...
chart_url = init_plotly_streaming_chart(
token=stream_ids[1],
maxpoints=50,
title="IB Streaming Demo")
print(chart_url)# create streamer
https://plot.ly/~ranaroussi/134
ticks = 0
def ibCallback(caller, msg, **kwargs):
global ticks
if "tick" in kwargs:
tick = ibConn.marketData[msg.tickerId]
streamer.write(dict(x=ticks, y=tick['last'].values[0]))
ticks += 1
tls.embed(chart_url)
streamer = ply.Stream(stream_ids[1])
streamer.open()
ibConn.connect(port=4001)
ibConn.ibCallback = ibCallback
contract = ibConn.createFuturesContract("ES",
exchange="GLOBEX", expiry="201709")
ibConn.requestMarketData()
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
print('Stopped by user...')
# cancel request and disconnect from TWS
ibConn.cancelMarketData(contract)
ibConn.disconnect()
streamer.close()
Server Version: 76 TWS Time at connection:20170824 18:50:47 IST
Stopped by user...
# market order
order = oanda.create_order(account_id,
instrument="EUR_USD",
units=1000,
side='buy',
type='market'
)
pretty_print(order)
{'instrument': 'EUR_USD', 'price': 1.18048, 'time': '2017-08-24T15:51:21.000000Z', 'tradeOpened': {'id': 10810337186, 'side': 'buy', 'stopLoss': 0, 'takeProfit': 0, 'trailingStop': 0, 'units': 1000}, 'tradeReduced': {}, 'tradesClosed': []}
# limit order
trade_expire = datetime.datetime.now() + datetime.timedelta(hours=1)
order = oanda.create_order(account_id,
instrument="EUR_USD",
units=1000,
side='buy',
type='limit',
price=1.1,
expiry = trade_expire.isoformat("T")
)
pretty_print(order)
{'instrument': 'EUR_USD', 'orderOpened': {'expiry': '2017-08-24T19:51:35.000000Z', 'id': 10810337470, 'lowerBound': 0, 'side': 'buy', 'stopLoss': 0, 'takeProfit': 0, 'trailingStop': 0, 'units': 1000, 'upperBound': 0}, 'price': 1.1, 'time': '2017-08-24T15:51:35.000000Z'}
# get trade, positions, orders information
positions = oanda.get_positions(account_id)
trades = oanda.get_trades(account_id)
orders = oanda.get_orders(account_id)
positions, trades, orders
({'positions': [{'avgPrice': 1.18048, 'instrument': 'EUR_USD', 'side': 'buy', 'units': 1000}]}, {'trades': [{'id': 10810337186, 'instrument': 'EUR_USD', 'price': 1.18048, 'side': 'buy', 'stopLoss': 0, 'takeProfit': 0, 'time': '2017-08-24T15:51:21.000000Z', 'trailingAmount': 0, 'trailingStop': 0, 'units': 1000}]}, {'orders': [{'expiry': '2017-08-24T19:51:35.000000Z', 'id': 10810337470, 'instrument': 'EUR_USD', 'lowerBound': 0, 'price': 1.1, 'side': 'buy', 'stopLoss': 0, 'takeProfit': 0, 'time': '2017-08-24T15:51:35.000000Z', 'trailingStop': 0, 'type': 'limit', 'units': 1000, 'upperBound': 0}]})
# close posiiton (market)
order = oanda.create_order(account_id,
instrument="EUR_USD",
units=1000,
type='market',
side='sell'
)
pretty_print(order)
{'instrument': 'EUR_USD', 'price': 1.18031, 'time': '2017-08-24T15:51:40.000000Z', 'tradeOpened': {}, 'tradeReduced': {}, 'tradesClosed': [{'id': 10810337186, 'side': 'buy', 'units': 1000}]}
# get trade, positions, orders information
positions = oanda.get_positions(account_id)
trades = oanda.get_trades(account_id)
orders = oanda.get_orders(account_id)
positions, trades, orders
({'positions': []}, {'trades': []}, {'orders': [{'expiry': '2017-08-24T19:51:35.000000Z', 'id': 10810337470, 'instrument': 'EUR_USD', 'lowerBound': 0, 'price': 1.1, 'side': 'buy', 'stopLoss': 0, 'takeProfit': 0, 'time': '2017-08-24T15:51:35.000000Z', 'trailingStop': 0, 'type': 'limit', 'units': 1000, 'upperBound': 0}]})
# close pending order
orderId = orders['orders'][0]['id']
oanda.close_order(account_id, orderId)
pretty_print(order)
{'instrument': 'EUR_USD', 'price': 1.18031, 'time': '2017-08-24T15:51:40.000000Z', 'tradeOpened': {}, 'tradeReduced': {}, 'tradesClosed': [{'id': 10810337186, 'side': 'buy', 'units': 1000}]}
# get trade, positions, orders information
positions = oanda.get_positions(account_id)
trades = oanda.get_trades(account_id)
orders = oanda.get_orders(account_id)
positions, trades, orders
({'positions': []}, {'trades': []}, {'orders': []})
import ezibpy
# initialize ezIBpy
ibConn = ezibpy.ezIBpy()
# create callback method
def ibCallback(caller, msg, **kwargs):
if caller == "handleOrders":
order = ibConn.orders[msg.orderId]
print('Order > ', order)
# issue market order
ibConn.connect(port=4001)
ibConn.ibCallback = ibCallback
contract = ibConn.createFuturesContract("ES",
exchange="GLOBEX", expiry="201709")
order = ibConn.createOrder(1)
orderId = ibConn.placeOrder(contract, order)
time.sleep(1)
ibConn.disconnect()
Server Version: 76 TWS Time at connection:20170824 18:51:52 IST Order > {'id': 196, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eb65d68>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 51, 52)} Order > {'id': 196, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eb65d68>, 'status': 'SUBMITTED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 51, 52)} Order > {'id': 196, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eb65d68>, 'status': 'FILLED', 'reason': None, 'avgFillPrice': 2424.75, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 51, 53)}
# get trade, positions, orders information
ibConn.positions, ibConn.portfolio, ibConn.orders
({'CLU2017_FUT': {'account': 'DU15012', 'avgCost': 0.0, 'position': 0, 'symbol': 'CLU2017_FUT'}, 'ESU2017_FUT': {'account': 'DU15012', 'avgCost': 121237.5, 'position': 1, 'symbol': 'ESU2017_FUT'}}, {'CLU2017_FUT': {'account': 'DU15012', 'averageCost': 0.0, 'marketPrice': 48.2200012, 'marketValue': 0.0, 'position': 0, 'realizedPNL': -540.0, 'symbol': 'CLU2017_FUT', 'totalPNL': -540.0, 'unrealizedPNL': 0.0}, 'ESU2017_FUT': {'account': 'DU15012', 'averageCost': 0.0, 'marketPrice': 2424.625, 'marketValue': 0.0, 'position': 0, 'realizedPNL': -2595.9, 'symbol': 'ESU2017_FUT', 'totalPNL': -2595.9, 'unrealizedPNL': 0.0}}, {196: {'avgFillPrice': 2424.75, 'id': 196, 'order': <ib.ext.Order.Order at 0x11eb65d68>, 'parentId': 0, 'reason': None, 'status': 'FILLED', 'symbol': 'ESU2017_FUT', 'time': datetime.datetime(2017, 8, 24, 18, 51, 53)}})
# bracker limit order
ibConn.connect(port=4001)
ibConn.ibCallback = ibCallback
contract = ibConn.createFuturesContract("ES",
exchange="GLOBEX", expiry="201709")
order = ibConn.createBracketOrder(
contract, quantity=1, entry=2400, target=2500., stop=2300.)
time.sleep(1)
ibConn.disconnect()
Server Version: 76 TWS Time at connection:20170824 18:52:04 IST Order > {'id': 198, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eefecc0>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 4)} Order > {'id': 198, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eefecc0>, 'status': 'PRESUBMITTED', 'reason': 'child,locate', 'avgFillPrice': 0.0, 'parentId': 197, 'time': datetime.datetime(2017, 8, 24, 18, 52, 4)} Order > {'id': 201, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ef06c18>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 5)} Order > {'id': 201, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ef06c18>, 'status': 'PRESUBMITTED', 'reason': 'child,locate,trigger', 'avgFillPrice': 0.0, 'parentId': 197, 'time': datetime.datetime(2017, 8, 24, 18, 52, 5)} Order > {'id': 197, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eeee9e8>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 5)} Order > {'id': 197, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eeee9e8>, 'status': 'SUBMITTED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 5)}
# get order information
pretty_print(ibConn.orders)
{196: {'avgFillPrice': 2424.75, 'id': 196, 'order': <ib.ext.Order.Order object at 0x11eb65d68>, 'parentId': 0, 'reason': None, 'status': 'FILLED', 'symbol': 'ESU2017_FUT', 'time': datetime.datetime(2017, 8, 24, 18, 51, 53)}, 197: {'avgFillPrice': 0.0, 'id': 197, 'order': <ib.ext.Order.Order object at 0x11eeee9e8>, 'parentId': 0, 'reason': None, 'status': 'SUBMITTED', 'symbol': 'ESU2017_FUT', 'time': datetime.datetime(2017, 8, 24, 18, 52, 5)}, 198: {'avgFillPrice': 0.0, 'id': 198, 'order': <ib.ext.Order.Order object at 0x11eefecc0>, 'parentId': 197, 'reason': 'child,locate', 'status': 'PRESUBMITTED', 'symbol': 'ESU2017_FUT', 'time': datetime.datetime(2017, 8, 24, 18, 52, 4)}, 201: {'avgFillPrice': 0.0, 'id': 201, 'order': <ib.ext.Order.Order object at 0x11ef06c18>, 'parentId': 197, 'reason': 'child,locate,trigger', 'status': 'PRESUBMITTED', 'symbol': 'ESU2017_FUT', 'time': datetime.datetime(2017, 8, 24, 18, 52, 5)}}
# build ohlc _bars
_bars = pd.DataFrame()
_ticks = pd.DataFrame()
_res = '1T'
_window = 100
def ibCallback(caller, msg, **kwargs):
global _bars, _ticks, _res, _window
if caller == "handleOrders":
order = ibConn.orders[msg.orderId]
print('Order > ', order)
elif "tick" in kwargs:
# read tick
tick = ibConn.marketData[msg.tickerId]
# add to _ticks df
_ticks = pd.concat([_ticks, tick])
_ticks.index = pd.to_datetime(_ticks.index)
# on_new_bar(_ticks.copy())
# return
# resample _ticks to 1min _bars
ticks_as_bars = _ticks['last'].resample(_res).ohlc()
ticks_as_bars['volume'] = _ticks['lastsize'].resample(_res).sum()
# replace latest bar data with resampled _ticks
_bars = _bars[_bars.index != ticks_as_bars.index[-1]]
_bars = pd.concat([_bars, ticks_as_bars[-1:]])
# remove old _ticks
pre_trimmed_ticks = len(_ticks)
_ticks = _ticks[_ticks.index >= ticks_as_bars.index[-1]]
# run strategy logic
if len(_ticks) != pre_trimmed_ticks:
on_new_bar(_bars[-_window:].copy())
def on_new_bar(bars):
position = 0
if contractString in ibConn.positions:
position = ibConn.positions[contractString]['position']
# calculate sma
bars['sma'] = bars['last'].rolling(2).mean()
# get lastest bar as dict
bar = bars.to_dict(orient='records')[-1]
order_qty = 0
if bar['last'] > bar['sma'] and position <= 0:
order_qty = abs(position) + 1
elif bar['last'] < bar['sma'] and position >= 0:
order_qty = -abs(position) - order_qty
# send order?
if order_qty != 0:
print('order qty ==>', order_qty)
order = ibConn.createOrder(order_qty)
ibConn.placeOrder(contract, order)
ibConn.connect(port=4001)
ibConn.ibCallback = ibCallback
contract = ibConn.createFuturesContract("ES",
exchange="GLOBEX", expiry="201709")
contractString = ibConn.contractString(contract)
ibConn.requestMarketData()
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
print('Stopped by user...')
# cancel request and disconnect from TWS
ibConn.cancelMarketData(contract)
ibConn.disconnect()
Server Version: 76 TWS Time at connection:20170824 18:52:40 IST
order qty ==> -1 order qty ==> -1 Order > {'id': 202, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ef1f160>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 40)} Order > {'id': 202, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ef1f160>, 'status': 'FILLED', 'reason': None, 'avgFillPrice': 2424.75, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 40)} Order > {'id': 203, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eb388d0>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 42)} Order > {'id': 203, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11eb388d0>, 'status': 'FILLED', 'reason': None, 'avgFillPrice': 2424.75, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 42)} order qty ==> 2 Order > {'id': 204, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ee6ee10>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 42)} Order > {'id': 204, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ee6ee10>, 'status': 'FILLED', 'reason': None, 'avgFillPrice': 2425.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 42)} order qty ==> -1 Order > {'id': 205, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ef06630>, 'status': 'OPENED', 'reason': None, 'avgFillPrice': 0.0, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 43)} Order > {'id': 205, 'symbol': 'ESU2017_FUT', 'order': <ib.ext.Order.Order object at 0x11ef06630>, 'status': 'FILLED', 'reason': None, 'avgFillPrice': 2424.75, 'parentId': 0, 'time': datetime.datetime(2017, 8, 24, 18, 52, 43)} order qty ==> 1 Stopped by user...
This was the part 3 out of the 4-part webinar series
© Ran Aroussi
@aroussi | aroussi.com | github.com/ranaroussi
August, 2017