mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-02 00:44:13 +08:00
@@ -40,9 +40,12 @@ Performance Tracking
|
||||
| | through all the events delivered to this tracker. |
|
||||
| | For details look at the comments for |
|
||||
| | :py:meth:`zipline.finance.risk.RiskMetrics.to_dict`|
|
||||
+-----------------+----------------------------------------------------+
|
||||
| exceeded_max_ | True if the simulation was stopped because single |
|
||||
| loss | day losses exceeded the max_drawdown stipulated in |
|
||||
| | trading_environment. |
|
||||
+-----------------+----------------------------------------------------+
|
||||
|
||||
|
||||
Position Tracking
|
||||
=================
|
||||
|
||||
@@ -154,6 +157,7 @@ class PerformanceTracker():
|
||||
self.result_stream = None
|
||||
self.last_dict = None
|
||||
self.order_log = []
|
||||
self.exceeded_max_loss = False
|
||||
|
||||
# this performance period will span the entire simulation.
|
||||
self.cumulative_performance = PerformancePeriod(
|
||||
@@ -213,7 +217,7 @@ class PerformanceTracker():
|
||||
'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(),
|
||||
'cumulative_risk_metrics' : self.cumulative_risk_metrics.to_dict()
|
||||
}
|
||||
|
||||
def log_order(self, order):
|
||||
@@ -263,11 +267,37 @@ class PerformanceTracker():
|
||||
# calculate progress of test
|
||||
self.progress = self.day_count / self.total_days
|
||||
|
||||
if self.trading_environment.max_drawdown:
|
||||
max_dd = -1 * self.trading_environment.max_drawdown
|
||||
if self.todays_performance.returns < max_dd:
|
||||
qutil.LOGGER.info("Exceeded max drawdown.")
|
||||
# mark the perf period with max loss flag,
|
||||
# so it shows up in the update, but don't end the test
|
||||
# here. Let the update go out before stopping
|
||||
self.exceeded_max_loss = True
|
||||
|
||||
# Output results
|
||||
if self.result_stream:
|
||||
msg = zp.PERF_FRAME(self.to_dict())
|
||||
self.result_stream.send(msg)
|
||||
|
||||
|
||||
if self.exceeded_max_loss:
|
||||
# now that we've sent the day's update, kill this test
|
||||
self.handle_simulation_end(skip_close=True)
|
||||
return
|
||||
|
||||
# check the day's returns versus the max drawdown
|
||||
# max_drawdown is optional:
|
||||
if self.trading_environment.max_drawdown:
|
||||
max_dd = -1 * self.trading_environment.max_drawdown
|
||||
if self.todays_performance.returns < max_dd:
|
||||
qutil.LOGGER.info("Exceeded max drawdown.")
|
||||
# TODO: any other information we need to relay on the
|
||||
# result socket?
|
||||
self.exceeded_max_loss = True
|
||||
self.handle_simulation_end(skip_close=True)
|
||||
return
|
||||
|
||||
#move the market day markers forward
|
||||
self.market_open = self.market_open + self.calendar_day
|
||||
|
||||
@@ -288,7 +318,7 @@ class PerformanceTracker():
|
||||
keep_transactions = True
|
||||
)
|
||||
|
||||
def handle_simulation_end(self):
|
||||
def handle_simulation_end(self, skip_close=False):
|
||||
"""
|
||||
When the simulation is complete, run the full period risk report
|
||||
and send it out on the result_stream.
|
||||
@@ -300,18 +330,21 @@ class PerformanceTracker():
|
||||
|
||||
# the stream will end on the last trading day, but will not trigger
|
||||
# an end of day, so we trigger the final market close here.
|
||||
self.handle_market_close()
|
||||
|
||||
# In the case of errors, we needn't close again.
|
||||
if not skip_close:
|
||||
self.handle_market_close()
|
||||
|
||||
self.risk_report = risk.RiskReport(
|
||||
self.returns,
|
||||
self.trading_environment
|
||||
self.trading_environment,
|
||||
exceeded_max_loss = self.exceeded_max_loss
|
||||
)
|
||||
|
||||
|
||||
if self.result_stream:
|
||||
qutil.LOGGER.info("about to stream the risk report...")
|
||||
report = self.risk_report.to_dict()
|
||||
msg = zp.RISK_FRAME(report)
|
||||
risk_dict = self.risk_report.to_dict()
|
||||
|
||||
msg = zp.RISK_FRAME(risk_dict)
|
||||
self.result_stream.send(msg)
|
||||
# this signals that the simulation is complete.
|
||||
self.result_stream.send("DONE")
|
||||
|
||||
+11
-5
@@ -315,7 +315,11 @@ class RiskMetrics():
|
||||
|
||||
class RiskReport():
|
||||
|
||||
def __init__(self, algorithm_returns, trading_environment):
|
||||
def __init__(
|
||||
self,
|
||||
algorithm_returns,
|
||||
trading_environment,
|
||||
exceeded_max_loss=False):
|
||||
"""
|
||||
algorithm_returns needs to be a list of daily_return objects
|
||||
sorted in date ascending order
|
||||
@@ -323,6 +327,7 @@ class RiskReport():
|
||||
|
||||
self.algorithm_returns = algorithm_returns
|
||||
self.trading_environment = trading_environment
|
||||
self.exceeded_max_loss = exceeded_max_loss
|
||||
|
||||
if len(self.algorithm_returns) == 0:
|
||||
start_date = self.trading_environment.period_start
|
||||
@@ -352,10 +357,11 @@ class RiskReport():
|
||||
provided for each period.
|
||||
"""
|
||||
return {
|
||||
'one_month' : [x.to_dict() for x in self.month_periods],
|
||||
'three_month' : [x.to_dict() for x in self.three_month_periods],
|
||||
'six_month' : [x.to_dict() for x in self.six_month_periods],
|
||||
'twelve_month' : [x.to_dict() for x in self.year_periods]
|
||||
'one_month' : [x.to_dict() for x in self.month_periods],
|
||||
'three_month' : [x.to_dict() for x in self.three_month_periods],
|
||||
'six_month' : [x.to_dict() for x in self.six_month_periods],
|
||||
'twelve_month' : [x.to_dict() for x in self.year_periods],
|
||||
'exceeded_max_loss' : self.exceeded_max_loss
|
||||
}
|
||||
|
||||
def periodsInRange(self, months_per, start, end):
|
||||
|
||||
@@ -99,6 +99,10 @@ class TradeSimulationClient(qmsg.Component):
|
||||
|
||||
def process_event(self, event):
|
||||
|
||||
if self.perf.exceeded_max_loss:
|
||||
self.control_out.send(str(zp.CONTROL_PROTOCOL.SHUTDOWN))
|
||||
return
|
||||
|
||||
# generate transactions, if applicable
|
||||
txn = self.txn_sim.apply_trade_to_open_orders(event)
|
||||
if txn:
|
||||
|
||||
@@ -663,6 +663,7 @@ def convert_transactions(transactions):
|
||||
for txn in transactions:
|
||||
txn['date'] = EPOCH(txn['dt'])
|
||||
del(txn['dt'])
|
||||
del(txn['source_id'])
|
||||
results.append(txn)
|
||||
return results
|
||||
|
||||
|
||||
Reference in New Issue
Block a user