Initial commit of IQFeed API client
This commit is contained in:
parent
f12b5edf8c
commit
71379aba8e
0
iqfeed/__init__.py
Normal file
0
iqfeed/__init__.py
Normal file
102
iqfeed/iqfeed.py
Normal file
102
iqfeed/iqfeed.py
Normal file
@ -0,0 +1,102 @@
|
||||
import pandas as pd
|
||||
import socket
|
||||
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
|
||||
def read_data_from_socket(sock, recv_buffer=4096):
|
||||
buffer = b''
|
||||
data = b''
|
||||
while True:
|
||||
data = sock.recv(recv_buffer)
|
||||
buffer += data
|
||||
|
||||
if b'!ENDMSG!' in buffer:
|
||||
break
|
||||
|
||||
# Remove the ENDMSG string
|
||||
buffer = buffer[:-12]
|
||||
return buffer.decode('utf-8')
|
||||
|
||||
def _get_daily_data(symbol: str, max_days: int) -> pd.DataFrame:
|
||||
host = '127.0.0.1'
|
||||
port = 9100 # Historical data socket port
|
||||
|
||||
message = 'HDX,{symbol},{max_days},1\n'.format(
|
||||
symbol=symbol,
|
||||
max_days=max_days
|
||||
)
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect((host, port))
|
||||
|
||||
sock.sendall(message.encode('utf-8'))
|
||||
data = read_data_from_socket(sock)
|
||||
sock.close()
|
||||
|
||||
# Remove extraneous line endings
|
||||
data = ''.join(data.split('\r'))
|
||||
data = data.replace(',\n','\n')[:-1]
|
||||
|
||||
data = StringIO(data)
|
||||
return pd.read_csv(data, index_col=False,
|
||||
names=['Date', 'High', 'Low', 'Open', 'Close', 'Total Volume', 'Period Volume'])
|
||||
|
||||
def get_daily_data(symbol: str, start_date: datetime, end_date: datetime) -> pd.DataFrame:
|
||||
max_days = (datetime.today() - start_date).days
|
||||
data = _get_daily_data(symbol, max_days)
|
||||
|
||||
# Filter data between start_date and end_date
|
||||
data['Date'] = pd.to_datetime(data['Date'])
|
||||
data['Date'] = data['Date'].dt.date
|
||||
data = data[(data['Date'] >= start_date.date()) & (data['Date'] <= end_date.date())]
|
||||
data = data.reset_index(drop=True)
|
||||
return data
|
||||
|
||||
def seconds(value):
|
||||
return value
|
||||
|
||||
def minutes(value):
|
||||
return value * 60
|
||||
|
||||
def hours(value):
|
||||
return value * 3600
|
||||
|
||||
def get_historical_data(symbol: str, interval: int,
|
||||
start_date: datetime, end_date: datetime = None,
|
||||
start_filter_time: datetime = datetime.strptime('093000', '%H%M%S').time(),
|
||||
end_filter_time: datetime = datetime.strptime('160000', '%H%M%S').time()) -> pd.DataFrame:
|
||||
host = '127.0.0.1'
|
||||
port = 9100 # Historical data socket port
|
||||
|
||||
message = 'HIT,{symbol},{interval},{begin},{end},,{begin_filter},{end_filter},1\n'.format(
|
||||
symbol=symbol,
|
||||
interval=interval,
|
||||
begin=start_date.strftime('%Y%m%d %H%M%S'),
|
||||
end=end_date.strftime('%Y%m%d %H%M%S') if end_date else '',
|
||||
begin_filter=start_filter_time.strftime('%H%M%S') if start_filter_time else '',
|
||||
end_filter=end_filter_time.strftime('%H%M%S') if end_filter_time else ''
|
||||
)
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect((host, port))
|
||||
|
||||
sock.sendall(message.encode('utf-8'))
|
||||
data = read_data_from_socket(sock)
|
||||
sock.close()
|
||||
|
||||
# Remove extraneous line endings
|
||||
data = ''.join(data.split('\r'))
|
||||
data = data.replace(',\n','\n')[:-1]
|
||||
|
||||
data = StringIO(data)
|
||||
return pd.read_csv(data, index_col=False,
|
||||
names=['Date', 'High', 'Low', 'Open', 'Close', 'Total Volume', 'Period Volume'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
symbols = ['SPY']
|
||||
start_date = datetime(2023, 1, 1, 7, 50)
|
||||
end_date = datetime(2023, 1, 31, 16, 0)
|
||||
for symbol in symbols:
|
||||
data = get_historical_data(symbol, minutes(5), start_date, end_date)
|
||||
data.to_csv(symbol + '.csv')
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
pandas
|
Loading…
Reference in New Issue
Block a user