Skip to content

Commit aa214f1

Browse files
add WebSocket trading example
1 parent 4585ec5 commit aa214f1

File tree

2 files changed

+238
-105
lines changed

2 files changed

+238
-105
lines changed

Alpaca_trading_example.py

Lines changed: 130 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import alpaca_trade_api as tradeapi
2-
import threading
3-
from time import *
41
import json
52
import logging
3+
import threading
4+
from time import *
65

7-
#init
8-
logging.basicConfig(filename='errlog.log',level=logging.WARNING, format='%(asctime)s:%(levelname)s:%(message)s')
6+
import alpaca_trade_api as tradeapi
7+
8+
# init
9+
logging.basicConfig(
10+
filename='errlog.log',
11+
level=logging.WARNING,
12+
format='%(asctime)s:%(levelname)s:%(message)s',
13+
)
914

1015
api_key = 'insert_api_key'
1116
api_secret = 'insert_api_secret'
@@ -23,132 +28,152 @@
2328
active_trade = False
2429
done_for_the_day = False
2530

26-
#check if market is open
31+
# check if market is open
2732
api.cancel_all_orders()
2833
clock = api.get_clock()
2934

3035
if clock.is_open:
31-
pass
36+
pass
3237
else:
33-
time_to_open = clock.next_open - clock.timestamp
34-
sleep(time_to_open.total_seconds())
38+
time_to_open = clock.next_open - clock.timestamp
39+
sleep(time_to_open.total_seconds())
3540

3641
if len(api.list_positions()) == 0:
37-
searching_for_trade = True
42+
searching_for_trade = True
3843
else:
39-
active_trade = True
44+
active_trade = True
4045

41-
#init WebSocket
46+
# init WebSocket
4247
conn = tradeapi.stream2.StreamConn(api_key, api_secret, base_url)
4348

49+
4450
@conn.on(r'^account_updates$')
4551
async def on_account_updates(conn, channel, account):
46-
order_msg.append(account)
52+
order_msg.append(account)
53+
4754

4855
@conn.on(r'^trade_updates$')
4956
async def on_trade_updates(conn, channel, trade):
50-
trade_msg.append(trade)
51-
if 'fill' in trade.event:
52-
past_trades.append([trade.order['updated_at'], trade.order['symbol'], trade.order['side'],
53-
trade.order['filled_qty'], trade.order['filled_avg_price']])
54-
with open('past_trades.csv', 'w') as f:
55-
json.dump(past_trades, f, indent=4)
56-
print(past_trades[-1])
57+
trade_msg.append(trade)
58+
if 'fill' in trade.event:
59+
past_trades.append(
60+
[
61+
trade.order['updated_at'],
62+
trade.order['symbol'],
63+
trade.order['side'],
64+
trade.order['filled_qty'],
65+
trade.order['filled_avg_price'],
66+
]
67+
)
68+
with open('past_trades.csv', 'w') as f:
69+
json.dump(past_trades, f, indent=4)
70+
print(past_trades[-1])
71+
5772

5873
def ws_start():
59-
conn.run(['account_updates', 'trade_updates'])
74+
conn.run(['account_updates', 'trade_updates'])
75+
6076

61-
#start WebSocket in a thread
77+
# start WebSocket in a thread
6278
ws_thread = threading.Thread(target=ws_start, daemon=True)
6379
ws_thread.start()
6480
sleep(10)
6581

6682

67-
#functions
83+
# functions
6884
def time_to_market_close():
69-
clock = api.get_clock()
70-
closing = clock.next_close - clock.timestamp
71-
return round(closing.seconds/60)
72-
73-
def send_order(direction):
74-
if time_to_market_close() > 20:
75-
if direction == 'buy':
76-
sl = high-range_size
77-
tp = high+range_size
78-
elif direction == 'sell':
79-
sl = low+range_size
80-
tp = low-range_size
85+
clock = api.get_clock()
86+
closing = clock.next_close - clock.timestamp
87+
return round(closing.total_seconds() / 60)
8188

82-
api.submit_order(symbol='AAPL', qty=100, side=direction, type='market', time_in_force='day', order_class='bracket', stop_loss=dict(stop_price=str(sl)), take_profit=dict(limit_price=str(tp)))
83-
return True, False
8489

85-
else:
86-
return False, True
87-
88-
89-
#main loop
90+
def send_order(direction):
91+
if time_to_market_close() > 20:
92+
if direction == 'buy':
93+
sl = high - range_size
94+
tp = high + range_size
95+
elif direction == 'sell':
96+
sl = low + range_size
97+
tp = low - range_size
98+
99+
api.submit_order(
100+
symbol='AAPL',
101+
qty=100,
102+
side=direction,
103+
type='market',
104+
time_in_force='day',
105+
order_class='bracket',
106+
stop_loss=dict(stop_price=str(sl)),
107+
take_profit=dict(limit_price=str(tp)),
108+
)
109+
return True, False
110+
111+
else:
112+
return False, True
113+
114+
115+
# main loop
90116
while True:
91117

92-
try:
93-
94-
candlesticks = api.get_barset('AAPL', 'minute', limit=10)
95-
high = candlesticks['AAPL'][0].h
96-
low = candlesticks['AAPL'][0].l
97-
range_size = high - low
98-
if range_size / candlesticks['AAPL'][0].c < 0.003:
99-
range_size = candlesticks['AAPL'][0].c * 0.003
100-
for candle in candlesticks['AAPL']:
101-
if candle.h > high:
102-
high = candle.h
103-
elif candle.l < low:
104-
low = candle.l
105-
range_size = high - low
106-
107-
while searching_for_trade:
108-
clock = api.get_clock()
109-
sleep(60-clock.timestamp.second)
110-
candlesticks = api.get_barset('AAPL', 'minute', limit=1)
111-
if candlesticks['AAPL'][0].c > high:
112-
searching_for_trade = False
113-
order_sent, done_for_the_day = send_order('buy')
114-
115-
elif candlesticks['AAPL'][0].c < low:
116-
searching_for_trade = False
117-
order_sent, done_for_the_day = send_order('sell')
118-
119-
while order_sent:
120-
sleep(1)
121-
for item in trade_msg:
122-
if item.event == 'new':
123-
order_submitted = True
124-
order_sent = False
125-
126-
while order_submitted:
127-
sleep(1)
128-
for item in trade_msg:
129-
if item.order['filled_qty'] == '100':
130-
order_submitted = False
131-
active_trade = True
132-
trade_msg = []
133-
134-
135-
while active_trade:
136-
for i in range(time_to_market_close()-5):
137-
sleep(60)
138-
if len(api.list_positions()) == 0:
139-
active_trade = False
140-
searching_for_trade = True
141-
break
142-
if active_trade:
143-
done_for_the_day = True
144-
active_trade = False
145-
146-
while done_for_the_day:
147-
api.close_all_positions()
148-
clock = api.get_clock()
149-
next_market_open = clock.next_open - clock.timestamp
150-
sleep(next_market_open.total_seconds())
151-
searching_for_trade = True
152-
153-
except Exception as e:
154-
logging.exception(e)
118+
try:
119+
120+
candlesticks = api.get_barset('AAPL', 'minute', limit=10)
121+
high = candlesticks['AAPL'][0].h
122+
low = candlesticks['AAPL'][0].l
123+
range_size = high - low
124+
if range_size / candlesticks['AAPL'][0].c < 0.003:
125+
range_size = candlesticks['AAPL'][0].c * 0.003
126+
for candle in candlesticks['AAPL']:
127+
if candle.h > high:
128+
high = candle.h
129+
elif candle.l < low:
130+
low = candle.l
131+
range_size = high - low
132+
133+
while searching_for_trade:
134+
clock = api.get_clock()
135+
sleep(60 - clock.timestamp.second)
136+
candlesticks = api.get_barset('AAPL', 'minute', limit=1)
137+
if candlesticks['AAPL'][0].c > high:
138+
searching_for_trade = False
139+
order_sent, done_for_the_day = send_order('buy')
140+
141+
elif candlesticks['AAPL'][0].c < low:
142+
searching_for_trade = False
143+
order_sent, done_for_the_day = send_order('sell')
144+
145+
while order_sent:
146+
sleep(1)
147+
for item in trade_msg:
148+
if item.event == 'new':
149+
order_submitted = True
150+
order_sent = False
151+
152+
while order_submitted:
153+
sleep(1)
154+
for item in trade_msg:
155+
if item.order['filled_qty'] == '100':
156+
order_submitted = False
157+
active_trade = True
158+
trade_msg = []
159+
160+
while active_trade:
161+
for i in range(time_to_market_close() - 5):
162+
sleep(60)
163+
if len(api.list_positions()) == 0:
164+
active_trade = False
165+
searching_for_trade = True
166+
break
167+
if active_trade:
168+
done_for_the_day = True
169+
active_trade = False
170+
171+
while done_for_the_day:
172+
api.close_all_positions()
173+
clock = api.get_clock()
174+
next_market_open = clock.next_open - clock.timestamp
175+
sleep(next_market_open.total_seconds())
176+
searching_for_trade = True
177+
178+
except Exception as e:
179+
logging.exception(e)

Alpaca_trading_example_ws.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import logging
2+
from time import sleep
3+
4+
import alpaca_trade_api as tradeapi
5+
import pandas as pd
6+
7+
# init
8+
logging.basicConfig(
9+
filename='errlog.log',
10+
level=logging.WARNING,
11+
format='%(asctime)s:%(levelname)s:%(message)s',
12+
)
13+
14+
api_key = 'insert_api_key'
15+
api_secret = 'insert_api_secret'
16+
base_url = 'https://paper-api.alpaca.markets'
17+
data_url = 'wss://data.alpaca.markets'
18+
19+
20+
# instantiate REST API
21+
api = tradeapi.REST(api_key, api_secret, base_url, api_version='v2')
22+
23+
# init WebSocket
24+
conn = tradeapi.stream2.StreamConn(
25+
api_key,
26+
api_secret,
27+
base_url=base_url,
28+
data_url=data_url,
29+
data_stream='alpacadatav1',
30+
)
31+
32+
33+
def time_to_market_close():
34+
clock = api.get_clock()
35+
return (clock.next_close - clock.timestamp).total_seconds()
36+
37+
38+
def wait_for_market_open():
39+
clock = api.get_clock()
40+
if not clock.is_open:
41+
time_to_open = (clock.next_open - clock.timestamp).total_seconds()
42+
sleep(round(time_to_open))
43+
44+
45+
def set_trade_params(df):
46+
return {
47+
'high': df.high.tail(10).max(),
48+
'low': df.low.tail(10).min(),
49+
'trade_taken': False,
50+
}
51+
52+
53+
def send_order(direction, bar):
54+
if time_to_market_close() > 120:
55+
print(f'sent {direction} trade')
56+
range_size = trade_params['high'] - trade_params['low']
57+
58+
if direction == 'buy':
59+
sl = bar.high - range_size
60+
tp = bar.high + range_size
61+
elif direction == 'sell':
62+
sl = bar.low + range_size
63+
tp = bar.low - range_size
64+
65+
api.submit_order(
66+
symbol='AAPL',
67+
qty=100,
68+
side=direction,
69+
type='market',
70+
time_in_force='day',
71+
order_class='bracket',
72+
stop_loss=dict(stop_price=str(sl)),
73+
take_profit=dict(limit_price=str(tp)),
74+
)
75+
76+
return True
77+
78+
wait_for_market_open()
79+
return False
80+
81+
82+
@conn.on(r'^AM.AAPL$')
83+
async def on_minute_bars(conn, channel, bar):
84+
if isinstance(candlesticks.df, pd.DataFrame):
85+
ts = pd.to_datetime(bar.timestamp, unit='ms')
86+
candlesticks.df.loc[ts] = [bar.open, bar.high, bar.low, bar.close, bar.volume]
87+
88+
if not trade_params['trade_taken']:
89+
if bar.high > trade_params['high']:
90+
trade_params['trade_taken'] = send_order('buy', bar)
91+
92+
elif bar.low < trade_params['low']:
93+
trade_params['trade_taken'] = send_order('sell', bar)
94+
95+
if time_to_market_close() > 120:
96+
wait_for_market_open()
97+
98+
99+
@conn.on(r'^trade_updates$')
100+
async def on_trade_updates(conn, channel, trade):
101+
if trade.order['order_type'] != 'market' and trade.order['filled_qty'] == '100':
102+
# trade closed - look for new trade
103+
trade_params = set_trade_params(candlesticks.df.AAPL)
104+
105+
106+
candlesticks = api.get_barset('AAPL', 'minute', limit=10)
107+
trade_params = set_trade_params(candlesticks.df.AAPL)
108+
conn.run(['AM.AAPL', 'trade_updates'])

0 commit comments

Comments
 (0)