mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-02 13:04:49 +08:00
105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
"""
|
|
Provides data handlers that can push messages to a qsim.simulator.DataFeed
|
|
"""
|
|
import datetime
|
|
import zmq
|
|
import json
|
|
import multiprocessing
|
|
import random
|
|
|
|
import qsim.util as qutil
|
|
import qsim.messaging as qmsg
|
|
|
|
class DataSource(object):
|
|
"""
|
|
Baseclass for data sources. Subclass and implement send_all - usually this
|
|
means looping through all records in a store, converting to a dict, and
|
|
calling send(map).
|
|
"""
|
|
def __init__(self, feed, source_id):
|
|
self.source_id = source_id
|
|
self.feed = feed
|
|
self.cur_event = None
|
|
self.context = None
|
|
self.data_socket = None
|
|
|
|
def start(self):
|
|
"""Launch the datasource in a separate process."""
|
|
proc = multiprocessing.Process(target=self.run)
|
|
proc.start()
|
|
|
|
|
|
def open(self):
|
|
"""create zmq context and socket"""
|
|
qutil.logger.info(
|
|
"starting data source:{source_id} on {addr}"
|
|
.format(source_id=self.source_id, addr=self.feed.data_address))
|
|
|
|
self.context = zmq.Context()
|
|
|
|
#create the data sink. Based on http://zguide.zeromq.org/py:tasksink2
|
|
self.data_socket = self.context.socket(zmq.PUSH)
|
|
self.data_socket.connect(self.feed.data_address)
|
|
|
|
#signal we are ready
|
|
sync = qmsg.FeedSync(self.feed, str(self.source_id))
|
|
sync.confirm()
|
|
|
|
def run(self):
|
|
"""Fully execute this datasource."""
|
|
self.open()
|
|
self.send_all()
|
|
self.close()
|
|
|
|
def send_all(self):
|
|
"""Subclasses must implement this method."""
|
|
raise NotImplementedError()
|
|
|
|
def send(self, event):
|
|
"""
|
|
event is expected to be a dict
|
|
sets source_id and type properties in the dict
|
|
sends to the data_socket.
|
|
"""
|
|
event['s'] = self.source_id
|
|
event['type'] = 'event'
|
|
self.data_socket.send(json.dumps(event))
|
|
|
|
def close(self):
|
|
"""
|
|
Close the zmq context and sockets.
|
|
"""
|
|
done_msg = {}
|
|
done_msg['type'] = 'DONE'
|
|
done_msg['s'] = self.source_id
|
|
self.data_socket.send(json.dumps(done_msg))
|
|
self.data_socket.close()
|
|
self.context.term()
|
|
qutil.logger.info("finished processing data source")
|
|
|
|
class RandomEquityTrades(DataSource):
|
|
"""Generates a random stream of trades for testing."""
|
|
|
|
def __init__(self, sid, feed, source_id, count):
|
|
DataSource.__init__(self, feed, source_id)
|
|
self.count = count
|
|
self.sid = sid
|
|
|
|
def send_all(self):
|
|
trade_start = datetime.datetime.now()
|
|
minute = datetime.timedelta(minutes=1)
|
|
price = random.uniform(5.0, 50.0)
|
|
|
|
for i in range(self.count):
|
|
price = price + random.uniform(-0.05, 0.05)
|
|
event = {'sid':self.sid,
|
|
'dt':qutil.format_date(trade_start + (minute * i)),
|
|
'price':price,
|
|
'volume':random.randrange(100,10000,100)}
|
|
self.send(event)
|
|
|
|
|
|
|
|
|
|
|