mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-21 12:30:16 +08:00
ENH: Wires minutely emission of data from performance tracker.
Wires up performance tracker so that when `emission_rate` is set to `minute`, the performance packets are sent out every minute, instead of once per day. Please note, the performance packets that are generated are not ready for prime time consumption, this patch is merely a step towards hooking up the ability to inspect minute data. Known issues: - The packets do not currently include risk information. Since we need to consider how this affects the denominators of the risk calculations.
This commit is contained in:
@@ -1030,3 +1030,43 @@ class TestPerformanceTracker(unittest.TestCase):
|
||||
event['TRANSACTION'] = txn
|
||||
|
||||
return event
|
||||
|
||||
def test_minute_tracker(self):
|
||||
""" Tests minute performance tracking."""
|
||||
exc_tz = pytz.timezone('US/Eastern')
|
||||
start_dt = trading.exchange_dt_in_utc(
|
||||
datetime.datetime(2013, 3, 1, 9, 30, tzinfo=exc_tz))
|
||||
end_dt = trading.exchange_dt_in_utc(
|
||||
datetime.datetime(2013, 3, 1, 16, 0, tzinfo=exc_tz))
|
||||
|
||||
sim_params = SimulationParameters(
|
||||
period_start=start_dt,
|
||||
period_end=end_dt,
|
||||
emission_rate='minute'
|
||||
)
|
||||
tracker = perf.PerformanceTracker(sim_params)
|
||||
|
||||
foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt)
|
||||
bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt)
|
||||
txn = Transaction(sid=foo_event_1.sid,
|
||||
amount=-25,
|
||||
dt=foo_event_1.dt,
|
||||
price=10.0,
|
||||
commission=0.50)
|
||||
foo_event_1.TRANSACTION = txn
|
||||
|
||||
foo_event_2 = factory.create_trade(
|
||||
'foo', 11.0, 20, start_dt + datetime.timedelta(minutes=1))
|
||||
bar_event_2 = factory.create_trade(
|
||||
'bar', 11.0, 20, start_dt + datetime.timedelta(minutes=1))
|
||||
|
||||
foo_event_3 = factory.create_trade(
|
||||
'foo', 12.0, 30, start_dt + datetime.timedelta(minutes=2))
|
||||
|
||||
tracker.process_event(foo_event_1)
|
||||
tracker.process_event(bar_event_1)
|
||||
messages = tracker.process_event(foo_event_2)
|
||||
tracker.process_event(bar_event_2)
|
||||
messages += tracker.process_event(foo_event_3)
|
||||
|
||||
self.assertEquals(2, len(messages))
|
||||
|
||||
@@ -161,6 +161,7 @@ class PerformanceTracker(object):
|
||||
self.capital_base = self.sim_params.capital_base
|
||||
self.cumulative_risk_metrics = \
|
||||
risk.RiskMetricsIterative(self.period_start)
|
||||
self.emission_rate = sim_params.emission_rate
|
||||
|
||||
# this performance period will span the entire simulation.
|
||||
self.cumulative_performance = PerformancePeriod(
|
||||
@@ -187,6 +188,7 @@ class PerformanceTracker(object):
|
||||
serialize_positions=True
|
||||
)
|
||||
|
||||
self.saved_dt = self.period_start
|
||||
self.returns = []
|
||||
# one indexed so that we reach 100%
|
||||
self.day_count = 0.0
|
||||
@@ -225,15 +227,27 @@ class PerformanceTracker(object):
|
||||
Creates a dictionary representing the state of this tracker.
|
||||
Returns a dict object of the form described in header comments.
|
||||
"""
|
||||
return {
|
||||
_dict = {
|
||||
'period_start': self.period_start,
|
||||
'period_end': self.period_end,
|
||||
'progress': self.progress,
|
||||
'capital_base': self.capital_base,
|
||||
'cumulative_perf': self.cumulative_performance.to_dict(),
|
||||
'daily_perf': self.todays_performance.to_dict(),
|
||||
'cumulative_risk_metrics': self.cumulative_risk_metrics.to_dict()
|
||||
}
|
||||
if self.emission_rate == 'daily':
|
||||
_dict.update({'cumulative_risk_metrics':
|
||||
self.cumulative_risk_metrics.to_dict(),
|
||||
'daily_perf':
|
||||
self.todays_performance.to_dict()})
|
||||
if self.emission_rate == 'minute':
|
||||
# Currently reusing 'todays_performance' for intraday trading
|
||||
# result, should be analogous, but has the potential for needing
|
||||
# its own configuration down the line.
|
||||
# Naming as intraday to make clear that these results are
|
||||
# being updated per minute
|
||||
_dict['intraday_perf'] = self.todays_performance.to_dict()
|
||||
|
||||
return _dict
|
||||
|
||||
def process_event(self, event):
|
||||
|
||||
@@ -242,8 +256,17 @@ class PerformanceTracker(object):
|
||||
|
||||
if event.type == zp.DATASOURCE_TYPE.TRADE:
|
||||
messages = []
|
||||
while event.dt > self.market_close and event.dt < self.last_close:
|
||||
messages.append(self.handle_market_close())
|
||||
|
||||
# This switch could also be handled by an inheritance
|
||||
# with a DailyPerformanceTracker and a MinutePerformanceTracker
|
||||
if self.emission_rate == 'daily':
|
||||
while (event.dt > self.market_close and
|
||||
event.dt < self.last_close):
|
||||
messages.append(self.handle_market_close())
|
||||
elif self.emission_rate == 'minute':
|
||||
if event.dt > self.saved_dt:
|
||||
messages.append(self.to_dict())
|
||||
self.saved_dt = event.dt
|
||||
|
||||
if event.TRANSACTION:
|
||||
self.txn_count += 1
|
||||
|
||||
@@ -74,6 +74,11 @@ log = logbook.Logger('Transaction Simulator')
|
||||
environment = None
|
||||
|
||||
|
||||
def exchange_dt_in_utc(dt):
|
||||
delorean = Delorean(dt, dt.tzinfo)
|
||||
return delorean.shift(pytz.utc.zone).datetime
|
||||
|
||||
|
||||
class TransactionSimulator(object):
|
||||
|
||||
def __init__(self):
|
||||
@@ -253,7 +258,8 @@ Last successful date: %s" % self.market_open)
|
||||
|
||||
class SimulationParameters(object):
|
||||
def __init__(self, period_start, period_end,
|
||||
capital_base=10e3):
|
||||
capital_base=10e3,
|
||||
emission_rate='daily'):
|
||||
|
||||
global environment
|
||||
if not environment:
|
||||
@@ -264,6 +270,8 @@ class SimulationParameters(object):
|
||||
self.period_end = period_end
|
||||
self.capital_base = capital_base
|
||||
|
||||
self.emission_rate = emission_rate
|
||||
|
||||
assert self.period_start <= self.period_end, \
|
||||
"Period start falls after period end."
|
||||
|
||||
|
||||
Reference in New Issue
Block a user