https://github.com/timolson/alphahub
This example code demonstrates usage of the alphahub.us API. It's written in Python and requires
the websockets
and requests
packages. It uses heartbeating to keep the connection alive and will automatically
reauthenticate and reconnect on any error.
- Python 3.7 or greater is required
pip install -r requirements.txt
- Provide your AlphaHub credentials by either:
- Set environment variables
ALPHAHUB_EMAIL
and/orALPHAHUB_PASSWORD
- if an environment variable is not found, then the
package
alphahub.creds
is imported and the attributesemail
andpassword
are used instead. Seesrc/alphahub/creds_example.py
- Set environment variables
set PYTHONPATH=src
python -m alphahub [algo_id]*
- if no algorithm ID's are given on the command-line, it defaults to using 14, 16, 17, and 18.
You can easily integrate the alphahub.Connection
class into your own program:
import asyncio
import alphahub
def on_signal(id:int,info:dict):
"""
:param id is integer ID of the algorithm sending the signal
:param info is a dictionary like this one taken from Minotaur-3:
{
"close":[
{"price":216.08,"side":"buy","symbol":"VRTX","timestamp":"2021-04-26 T14:30:00"},
{"price":87.1,"side":"sell","symbol":"MU","timestamp":"2021-04-26T14:30:00"},
{"price":80.28,"side":"sell"," symbol":"BMRN","timestamp":"2021-04-26T14:30:00"}
],
"open":[
{"price":168.56,"side":"buy","symbol":"JBHT","timestamp":"2021-04-26T14:30:01"},
{"price":414.6,"side":"buy","symbol":"ILMN","timestamp":"2021-04-26T14:30:01"},
{"price":142.94,"side":"sell","symbol":"CDNS","timestamp":"2021-04-26T14:30:01"}
]
}
"""
print('SIGNAL',id,info)
email = 'my@email.com'
password = 'abc123'
algo_ids = [14,16,17,18]
conn = alphahub.Connection(email,password,algo_ids,on_signal)
asyncio.run(conn.run())
The Connection
class is a simple finite state machine and on any error it goes back to the initial state, causing a
re-authentication and new websockets connection to occur.
NOTE that this is 99% reliable, but if the connection drops just before a signal is published, and the connection is not reestablished until after the signal was pushed, then the signal message will be missed. High-availability would require multiple connections from different locations, and/or a change to the API to request missed signals.
Each signal has an integer ID assigned by AlphaHub:
14
Minotaur 1-Stock16
Minotaur 3-Stock17
Minotaur Optimus 118
The Optimizer
If your signal isn't listed here, just browse to the signal page on alphahub.us and look at the URL:
https://alphahub.us/algorithms/18
would be signal ID 18
The API authenticates with a REST-based OAuth request:
url = 'https://alphahub.us/api/v1/session'
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
params = {'user[email]': email, 'user[password]': password}
response = requests.post(url, params, headers=headers)
Response:
{'data': {'renew_token': 'ABC...', 'token': 'ABC...'}}
The authentication token expires after 30 minutes but within that window may be used to create a WebSockets connection:
url = f'wss://alphahub.us/socket/websocket?vsn=2.0.0&api_token={token}'
ws = await websockets.connect(url)
The rest of the communication is over the websocket.
After connecting the websocket, you may make multiple signal subscription requests:
ws.send(json.dumps([None,None,f'algorithms:{id}','phx_join',{}]))
Response:
[null,null,"algorithms:14","phx_reply",{"response":{},"status":"ok"}]
The websocket connection will timeout and not produce signals unless you keep it active with an application-level heartbeat. NOTE: this app-level heartbeat is in addition to the usual websockets protocol-level ping/pong mechanism. The application timeout is about one minute, so we send a heartbeat about every 15 seconds:
Heartbeat request:
[null,null,"phoenix","heartbeat",{}]
Heartbeat response:
[null,null,"phoenix","phx_reply",{"response":{},"status":"ok"}]
If the connection is up and you are heartbeating properly, then when new signals are published, you should receive a signal message for each signal you are subscribed to.
Signal message (pushed):
[
null,
null,
"algorithms:16",
"new_signals",
{
"close":[
{"price":216.08,"side":"buy","symbol":"VRTX","timestamp":"2021-04-26 T14:30:00"},
{"price":87.1,"side":"sell","symbol":"MU","timestamp":"2021-04-26T14:30:00"},
{"price":80.28,"side":"sell"," symbol":"BMRN","timestamp":"2021-04-26T14:30:00"}
],
"open":[
{"price":168.56,"side":"buy","symbol":"JBHT","timestamp":"2021-04-26T14:30:01"},
{"price":414.6,"side":"buy","symbol":"ILMN","timestamp":"2021-04-26T14:30:01"},
{"price":142.94,"side":"sell","symbol":"CDNS","timestamp":"2021-04-26T14:30:01"}
]
}
]
The info
argument passed to the alphahub.Connection.on_message(id,info)
method is the last item of this message
list.