request.post from Python to access Liberator Data
The request.post is an internet request method to request that the liberator server accept the data enclosed arguments and process the request.
Post Arguments:
- 'https://api.cloudquant.ai/liberator/query'
- This is the url of the query interface. This must be this exact string to query.
- data=json.dumps({"compress":compressed_transfer, "json_xfer":False, "user":user, "token":token, "name":name, "as_of":as_of, "back_to":back_to, "symbols":symbols, "system":"API"})
- This json.dumps section provides the body of the query.
- headers={'Content-Type':'application/json'},
- cert=cert,
- cert comes from with pfx_to_pem('liberator.pfx','') as cert: ro
- stream=True
Query the Last Known Value(s)
To get the last known value in any dataset simply do not provide the as_of or back_to arguments. This will give you the last known value for the given dataset and symbols.
Query for a Time Series Result
Adding the back_to argument for any query will give you the time series data all the way back to the specified back to date.
Every dataset has different data frequencies. We suggest using short time frames until you become familiar with the datasets, some of our datasets are quite large and thus an over-extended request may result in an extremely large amount of data returned.
json.dumps components
Argument |
Description |
Type |
Example |
symbols |
The security trading symbol(s) you wish to query |
string, or list |
"symbols":[“AAPL”,”TLT”,”GOOG”] |
name |
The name of the dataset (Required) |
String |
“name”: “daily_bars” |
as _of |
This value can be any past date so that you can see the data as it was known on the “as of” date. |
String |
“as_of”:“2020-11-22 19:51:31” |
back_to |
The date where the return dataset should begin. This is reading all the data “back to” the specified date. |
String |
“back_to”:“2020-01-01” |
url |
Optional. The url of the liberator server that you are querying. This defaults to 'https://api.cloudquant.ai'. You can also set it to an IP Address. E.g. 'http://127.0.0.1: 47753' |
String |
'https://api.cloudquant.ai' Or 'http://127.0.0.1: 47753' |
system |
The name of the authorized system from which you are querying. The security mechanism in liberator authorized users for individual systems. |
String This is almost always “API” |
“system”:“API” |
compress |
The data compression method on the wire. CloudQuant uses compression. |
Boolean |
True or False |
json_xfer |
Json transfer. This is usually False |
Boolean. Always False |
"json_xfer":False, |
user |
The user identifier (as assigned by CloudQuant) |
String |
"user":”myUserID” |
token |
The user’s assigned token |
String |
"token":”mypersonal-private-token” |
Example Calling the Liberator REST API with Python
Example Code for calling query interface in liberator using POST can be found in under_the_hood.py.
import sys
import zlib
import json
import base64
import requests
import tempfile
import contextlib
import pyarrow as pa
import OpenSSL.crypto
# from a gist
@contextlib.contextmanager
def pfx_to_pem(pfx_path, pfx_password):
''' Decrypts the .pfx file to be used with requests. '''
with tempfile.NamedTemporaryFile(suffix='.pem') as t_pem:
t_pem.close()
f_pem = open(t_pem.name, 'wb')
pfx = open(pfx_path, 'rb').read()
p12 = OpenSSL.crypto.load_pkcs12(pfx, pfx_password)
f_pem.write(OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey()))
f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate()))
ca = p12.get_ca_certificates()
if ca is not None:
for cert in ca:
f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert))
f_pem.close()
yield t_pem.name
compressed_transfer=True
# POST the query and prepare for a stream of single-line JSON replies
with pfx_to_pem('liberator.pfx','') as cert:
r=requests.post('https://api.cloudquant.ai/liberator/query',
data=json.dumps({"compress":compressed_transfer,"json_xfer":False,
"user":user,"token":token,
"name":name,"as_of":as_of,"back_to":back_to,"symbols":symbols,
"system":"API"}),
headers={'Content-Type':'application/json'},
cert=cert,
stream=True)
# ensure that the request was successful
if r.status_code!=200:
print(r.json())
else:
batches=[]
for line in r.iter_lines(4096):
# Show progress
print('.',end='')
sys.stdout.flush()
# The response stream contains informational messages other than "batch"
if line[0:14] == b'{"exception":"':
print('Error: '+json.loads(''.join([chr(c) for c in line]), encoding='latin-1')['value'])
break
if line[0:10] != b'{"batch":"':
continue
# cut out the payload from the JSON line w/o json module overhead
decoded=base64.b64decode(line[10:-3]) # "},
# interpret the payload as an Apache Arrow IPC stream
reader=pa.ipc.open_stream(zlib.decompress(decoded) if compressed_transfer else decoded)
# accumulate RecordBatch objects in a list
batches.extend([batch for batch in reader])
print('')
if batches:
# create an Arrow Table view on the batches and convert (e.g.) to a pandas DataFrame
df=pa.Table.from_batches(batches).to_pandas()
if 'muts' in df and '_seq' in df:
# by default, the data is sorted by symbol... re-sort by time
df=df.sort_values(['muts', '_seq'])
df.reset_index(drop=True,inplace=True)
print(df)