mirror of
https://github.com/wassname/catalyst.git
synced 2026-08-17 11:16:40 +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 |
|
| 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 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 |
|
| key | value |
|
||||||
+===============+======================================================+
|
+===============+======================================================+
|
||||||
@@ -190,7 +199,7 @@ class PerformanceTracker(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_portfolio(self):
|
def get_portfolio(self):
|
||||||
return self.cumulative_performance.to_ndict()
|
return self.cumulative_performance.as_portfolio()
|
||||||
|
|
||||||
def open(self, context):
|
def open(self, context):
|
||||||
if self.results_addr:
|
if self.results_addr:
|
||||||
@@ -247,12 +256,12 @@ class PerformanceTracker(object):
|
|||||||
self.cumulative_performance.update_last_sale(event)
|
self.cumulative_performance.update_last_sale(event)
|
||||||
self.todays_performance.update_last_sale(event)
|
self.todays_performance.update_last_sale(event)
|
||||||
|
|
||||||
|
|
||||||
def handle_market_close(self):
|
|
||||||
#calculate performance as of last trade
|
#calculate performance as of last trade
|
||||||
self.cumulative_performance.calculate_performance()
|
self.cumulative_performance.calculate_performance()
|
||||||
self.todays_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.
|
# 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_date = self.market_close.replace(hour=0, minute=0, second=0)
|
||||||
todays_return_obj = risk.DailyReturn(
|
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_price = event.price
|
||||||
self.positions[event.sid].last_sale_date = event.dt
|
self.positions[event.sid].last_sale_date = event.dt
|
||||||
|
|
||||||
def to_dict(self):
|
def __core_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]
|
|
||||||
|
|
||||||
rval = {
|
rval = {
|
||||||
'ending_value' : self.ending_value,
|
'ending_value' : self.ending_value,
|
||||||
'capital_used' : self.period_capital_used,
|
'capital_used' : self.period_capital_used,
|
||||||
@@ -508,46 +510,69 @@ class PerformancePeriod(object):
|
|||||||
'cumulative_capital_used' : self.cumulative_capital_used,
|
'cumulative_capital_used' : self.cumulative_capital_used,
|
||||||
'max_capital_used' : self.max_capital_used,
|
'max_capital_used' : self.max_capital_used,
|
||||||
'max_leverage' : self.max_leverage,
|
'max_leverage' : self.max_leverage,
|
||||||
'positions' : positions,
|
|
||||||
'pnl' : self.pnl,
|
'pnl' : self.pnl,
|
||||||
'returns' : self.returns,
|
'returns' : self.returns,
|
||||||
'transactions' : transactions,
|
|
||||||
'period_open' : self.period_open,
|
'period_open' : self.period_open,
|
||||||
'period_close' : self.period_close
|
'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
|
# we want the key to be absent, not just empty
|
||||||
if not self.keep_transactions:
|
if self.keep_transactions:
|
||||||
del rval['transactions']
|
transactions = [x.as_dict() for x in self.processed_transactions]
|
||||||
|
rval['transactions'] = transactions
|
||||||
|
|
||||||
return rval
|
return rval
|
||||||
|
|
||||||
def to_ndict(self):
|
def as_portfolio(self):
|
||||||
"""
|
"""
|
||||||
Creates a ndict representing the state of this perfomance period.
|
The purpose of this method is to provide a portfolio
|
||||||
Properties are the same as the results of to_dict. See header comments
|
object to algorithms running inside the same trading
|
||||||
for a detailed description.
|
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({
|
portfolio['positions'] = self.get_positions(ndicted=True)
|
||||||
'ending_value' : self.ending_value,
|
return zp.ndict(portfolio)
|
||||||
'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
|
|
||||||
})
|
|
||||||
|
|
||||||
def get_positions(self, ndicted=False):
|
def get_positions(self, ndicted=False):
|
||||||
positions = {}
|
if ndicted:
|
||||||
|
positions = zp.ndict({})
|
||||||
|
else:
|
||||||
|
positions = {}
|
||||||
|
|
||||||
for sid, pos in self.positions.iteritems():
|
for sid, pos in self.positions.iteritems():
|
||||||
cur = pos.to_dict()
|
cur = pos.to_dict()
|
||||||
if ndicted:
|
if ndicted:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Risk Report
|
|||||||
| alpha | The _algorithm_ alpha to the benchmark. |
|
| alpha | The _algorithm_ alpha to the benchmark. |
|
||||||
+-----------------+----------------------------------------------------+
|
+-----------------+----------------------------------------------------+
|
||||||
| excess_return | The excess return of the algorithm over the |
|
| excess_return | The excess return of the algorithm over the |
|
||||||
| | benchmark. |
|
| | treasuries. |
|
||||||
+-----------------+----------------------------------------------------+
|
+-----------------+----------------------------------------------------+
|
||||||
| max_drawdown | The largest relative peak to relative trough move |
|
| max_drawdown | The largest relative peak to relative trough move |
|
||||||
| | for the portfolio returns between self.start_date |
|
| | for the portfolio returns between self.start_date |
|
||||||
@@ -187,6 +187,8 @@ class RiskMetrics():
|
|||||||
return period_returns, returns
|
return period_returns, returns
|
||||||
|
|
||||||
def calculate_volatility(self, daily_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)
|
return np.std(daily_returns, ddof=1) * math.sqrt(self.trading_days)
|
||||||
|
|
||||||
def calculate_sharpe(self):
|
def calculate_sharpe(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user