Add script to download historical tick data from Sierra Chart's DTC server
This commit is contained in:
parent
ab17f59778
commit
14a6973599
120
download_historical_tick_data.py
Normal file
120
download_historical_tick_data.py
Normal file
@ -0,0 +1,120 @@
|
||||
############################################################################################################
|
||||
# Not using this as it turns out you can't download historical tick data from CME Group exchanges via DTC. #
|
||||
# Reference: https://www.sierrachart.com/index.php?page=doc/DTCServer.php#Restrictions #
|
||||
############################################################################################################
|
||||
|
||||
import socket
|
||||
import json
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from os import getenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# DTC Protocol Constants
|
||||
ENCODING_REQUEST = 6
|
||||
HISTORICAL_PRICE_DATA_REQUEST = 800
|
||||
INTERVAL_TICK = 0
|
||||
LOGON_REQUEST = 1
|
||||
LOGON_RESPONSE = 2
|
||||
LOGON_SUCCESS = 1
|
||||
|
||||
NULL_TERMINATOR = b'\x00'
|
||||
|
||||
class EncodingRequest:
|
||||
def __init__(self):
|
||||
self.Type = ENCODING_REQUEST
|
||||
self.ProtocolVersion = 8 # Set desired DTC Protocol version.
|
||||
self.Encoding = 2 # Set desired encoding (JSON).
|
||||
self.ProtocolType = 'DTC'
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.__dict__)
|
||||
|
||||
class LogonRequest:
|
||||
def __init__(self, username, password):
|
||||
self.Type = LOGON_REQUEST
|
||||
self.ProtocolVersion = 8 # Set desired DTC Protocol version.
|
||||
self.Username = username
|
||||
self.Password = password
|
||||
self.HeartbeatIntervalInSeconds = 30
|
||||
self.ClientName = 'Python DTC Client'
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.__dict__)
|
||||
|
||||
def authenticate_with_sierra_chart(client, username, password):
|
||||
print('Sending Encoding Request')
|
||||
encoding_request = EncodingRequest()
|
||||
encoded_request = encoding_request.to_json().encode() + NULL_TERMINATOR
|
||||
client.sendall(encoded_request)
|
||||
|
||||
encoding_response = client.recv(4096).decode().rstrip(NULL_TERMINATOR)
|
||||
print('Encoding Response: ', encoding_response)
|
||||
|
||||
print('Sending Logon Request')
|
||||
logon_request = LogonRequest(username, password)
|
||||
encoded_request = logon_request.to_json().encode('ascii') + NULL_TERMINATOR
|
||||
client.sendall(encoded_request)
|
||||
|
||||
response = client.recv(4096).decode().rstrip(NULL_TERMINATOR)
|
||||
print('Logon Response: ', response)
|
||||
data = json.loads(response)
|
||||
return data['Type'] == LOGON_RESPONSE and data.get('Result', -1) == LOGON_SUCCESS
|
||||
|
||||
class HistoricalPriceDataRequest:
|
||||
def __init__(self, symbol, exchange, start_date, end_date):
|
||||
self.Type = HISTORICAL_PRICE_DATA_REQUEST
|
||||
self.RequestID = 1
|
||||
self.Symbol = symbol
|
||||
self.Exchange = exchange
|
||||
self.RecordInterval = INTERVAL_TICK
|
||||
self.StartDateTime = start_date
|
||||
self.EndDateTime = end_date
|
||||
self.MaxDaysToReturn = 0
|
||||
self.UseZLibCompression = 1
|
||||
self.RequestDividendAdjustedStockData = 0
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.__dict__)
|
||||
|
||||
def listen_for_messages(client):
|
||||
messages = []
|
||||
while True:
|
||||
response = client.recv(4096).decode().rstrip(NULL_TERMINATOR)
|
||||
if not response:
|
||||
break
|
||||
data = json.loads(response)
|
||||
messages.append(data)
|
||||
if data['Type'] != 701: # "Waiting" message.
|
||||
break
|
||||
return messages
|
||||
|
||||
def request_data_from_sierra_chart(host, port, symbol, exchange, start_date, end_date):
|
||||
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
client.connect((host, port))
|
||||
|
||||
if not authenticate_with_sierra_chart(client, getenv('SIERRA_CHART_USERNAME'), getenv('SIERRA_CHART_PASSWORD')):
|
||||
print('Authentication failed.')
|
||||
client.close()
|
||||
return
|
||||
|
||||
request = HistoricalPriceDataRequest(symbol, exchange, start_date, end_date)
|
||||
encoded_request = request.to_json().encode() + NULL_TERMINATOR
|
||||
client.sendall(encoded_request)
|
||||
|
||||
messages = listen_for_messages(client)
|
||||
for message in messages:
|
||||
print(message) # Store this data or process it as needed.
|
||||
|
||||
client.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
HOST = '127.0.0.1'
|
||||
PORT = 11098 # Default DTC Protocol port for historical data.
|
||||
SYMBOL = 'MYMZ22-CBOT'
|
||||
EXCHANGE = 'CBOT'
|
||||
START_DATE = 20221001000000 # YYYYMMDDHHMMSS
|
||||
END_DATE = 20221001235959
|
||||
|
||||
request_data_from_sierra_chart(HOST, PORT, SYMBOL, EXCHANGE, START_DATE, END_DATE)
|
Loading…
Reference in New Issue
Block a user