mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-28 11:03:38 +08:00
Merge pull request #65 from quantopian/fawce_alpha1
portfolio object creation from PerformancePeriod
This commit is contained in:
@@ -59,11 +59,20 @@ Position Tracking
|
||||
+-----------------+----------------------------------------------------+
|
||||
| last_sale_price | price at last sale of the security on the exchange |
|
||||
+-----------------+----------------------------------------------------+
|
||||
| cost_basis | the volume weighted average price paid per share |
|
||||
+-----------------+----------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
Performance Period
|
||||
==================
|
||||
|
||||
Performance Periods are updated with every trade. When calling
|
||||
code needs a portfolio object that fulfills the algorithm
|
||||
protocol, use the PerformancePeriod.as_portfolio method. See that
|
||||
method for comments on the specific fields provided (and
|
||||
omitted).
|
||||
|
||||
+---------------+------------------------------------------------------+
|
||||
| key | value |
|
||||
+===============+======================================================+
|
||||
@@ -190,7 +199,7 @@ class PerformanceTracker(object):
|
||||
)
|
||||
|
||||
def get_portfolio(self):
|
||||
return self.cumulative_performance.to_ndict()
|
||||
return self.cumulative_performance.as_portfolio()
|
||||
|
||||
def open(self, context):
|
||||
if self.results_addr:
|
||||
@@ -247,12 +256,12 @@ class PerformanceTracker(object):
|
||||
self.cumulative_performance.update_last_sale(event)
|
||||
self.todays_performance.update_last_sale(event)
|
||||
|
||||
|
||||
def handle_market_close(self):
|
||||
#calculate performance as of last trade
|
||||
self.cumulative_performance.calculate_performance()
|
||||
self.todays_performance.calculate_performance()
|
||||
|
||||
def handle_market_close(self):
|
||||
|
||||
# add the return results from today to the list of DailyReturn objects.
|
||||
todays_date = self.market_close.replace(hour=0, minute=0, second=0)
|
||||
todays_return_obj = risk.DailyReturn(
|
||||
@@ -490,14 +499,7 @@ class PerformancePeriod(object):
|
||||
self.positions[event.sid].last_sale_price = event.price
|
||||
self.positions[event.sid].last_sale_date = event.dt
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Creates a dictionary representing the state of this performance
|
||||
period. See header comments for a detailed description.
|
||||
"""
|
||||
positions = self.get_positions_list()
|
||||
transactions = [x.as_dict() for x in self.processed_transactions]
|
||||
|
||||
def __core_dict(self):
|
||||
rval = {
|
||||
'ending_value' : self.ending_value,
|
||||
'capital_used' : self.period_capital_used,
|
||||
@@ -508,46 +510,69 @@ class PerformancePeriod(object):
|
||||
'cumulative_capital_used' : self.cumulative_capital_used,
|
||||
'max_capital_used' : self.max_capital_used,
|
||||
'max_leverage' : self.max_leverage,
|
||||
'positions' : positions,
|
||||
'pnl' : self.pnl,
|
||||
'returns' : self.returns,
|
||||
'transactions' : transactions,
|
||||
'period_open' : self.period_open,
|
||||
'period_close' : self.period_close
|
||||
}
|
||||
|
||||
return rval
|
||||
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Creates a dictionary representing the state of this performance
|
||||
period. See header comments for a detailed description.
|
||||
"""
|
||||
rval = self.__core_dict()
|
||||
positions = self.get_positions_list()
|
||||
rval['positions'] = positions
|
||||
|
||||
# we want the key to be absent, not just empty
|
||||
if not self.keep_transactions:
|
||||
del rval['transactions']
|
||||
if self.keep_transactions:
|
||||
transactions = [x.as_dict() for x in self.processed_transactions]
|
||||
rval['transactions'] = transactions
|
||||
|
||||
return rval
|
||||
|
||||
def to_ndict(self):
|
||||
def as_portfolio(self):
|
||||
"""
|
||||
Creates a ndict representing the state of this perfomance period.
|
||||
Properties are the same as the results of to_dict. See header comments
|
||||
for a detailed description.
|
||||
|
||||
The purpose of this method is to provide a portfolio
|
||||
object to algorithms running inside the same trading
|
||||
client. The data needed is captured raw in a
|
||||
PerformancePeriod, and in this method we rename some
|
||||
fields for usability and remove extraneous fields.
|
||||
"""
|
||||
positions = self.get_positions(ndicted=True)
|
||||
portfolio = self.__core_dict()
|
||||
# rename:
|
||||
# ending_cash -> cash
|
||||
# period_open -> backtest_start
|
||||
#
|
||||
# remove:
|
||||
# period_close, starting_value,
|
||||
# cumulative_capital_used, max_leverage, max_capital_used
|
||||
portfolio['cash'] = portfolio['ending_cash']
|
||||
portfolio['start_date'] = portfolio['period_open']
|
||||
portfolio['position_value'] = portfolio['ending_value']
|
||||
|
||||
positions = zp.ndict(positions)
|
||||
del(portfolio['ending_cash'])
|
||||
del(portfolio['period_open'])
|
||||
del(portfolio['period_close'])
|
||||
del(portfolio['starting_value'])
|
||||
del(portfolio['ending_value'])
|
||||
del(portfolio['cumulative_capital_used'])
|
||||
del(portfolio['max_leverage'])
|
||||
del(portfolio['max_capital_used'])
|
||||
|
||||
return zp.ndict({
|
||||
'ending_value' : self.ending_value,
|
||||
'capital_used' : self.period_capital_used,
|
||||
'starting_value' : self.starting_value,
|
||||
'starting_cash' : self.starting_cash,
|
||||
'ending_cash' : self.ending_cash,
|
||||
'cumulative_capital_used' : self.cumulative_capital_used,
|
||||
'max_capital_used' : self.max_capital_used,
|
||||
'max_leverage' : self.max_leverage,
|
||||
'positions' : positions,
|
||||
'transactions' : self.processed_transactions
|
||||
})
|
||||
portfolio['positions'] = self.get_positions(ndicted=True)
|
||||
return zp.ndict(portfolio)
|
||||
|
||||
def get_positions(self, ndicted=False):
|
||||
positions = {}
|
||||
if ndicted:
|
||||
positions = zp.ndict({})
|
||||
else:
|
||||
positions = {}
|
||||
|
||||
for sid, pos in self.positions.iteritems():
|
||||
cur = pos.to_dict()
|
||||
if ndicted:
|
||||
|
||||
@@ -27,7 +27,7 @@ Risk Report
|
||||
| alpha | The _algorithm_ alpha to the benchmark. |
|
||||
+-----------------+----------------------------------------------------+
|
||||
| excess_return | The excess return of the algorithm over the |
|
||||
| | benchmark. |
|
||||
| | treasuries. |
|
||||
+-----------------+----------------------------------------------------+
|
||||
| max_drawdown | The largest relative peak to relative trough move |
|
||||
| | for the portfolio returns between self.start_date |
|
||||
@@ -187,6 +187,8 @@ class RiskMetrics():
|
||||
return period_returns, returns
|
||||
|
||||
def calculate_volatility(self, daily_returns):
|
||||
# TODO: we should be using an annualized number for the
|
||||
# square root, not the days in the period.
|
||||
return np.std(daily_returns, ddof=1) * math.sqrt(self.trading_days)
|
||||
|
||||
def calculate_sharpe(self):
|
||||
|
||||
Reference in New Issue
Block a user