fixed a few type-os to repair document generation.

This commit is contained in:
fawce
2012-03-13 23:31:22 -04:00
parent cb07f2179d
commit 84bccbc67c
8 changed files with 423 additions and 127 deletions
+3 -3
View File
@@ -1,10 +1,10 @@
finance Package
===============
:mod:`data` Module
------------------
:mod:`performance` Module
-------------------------
.. automodule:: zipline.finance.data
.. automodule:: zipline.finance.performance
:members:
:undoc-members:
:show-inheritance:
+17 -8
View File
@@ -9,14 +9,6 @@ zipline Package
:undoc-members:
:show-inheritance:
:mod:`cli` Module
-----------------
.. automodule:: zipline.cli
:members:
:undoc-members:
:show-inheritance:
:mod:`component` Module
-----------------------
@@ -57,6 +49,14 @@ zipline Package
:undoc-members:
:show-inheritance:
:mod:`simulator` Module
-----------------------
.. automodule:: zipline.simulator
:members:
:undoc-members:
:show-inheritance:
:mod:`sources` Module
---------------------
@@ -65,6 +65,14 @@ zipline Package
:undoc-members:
:show-inheritance:
:mod:`topology` Module
----------------------
.. automodule:: zipline.topology
:members:
:undoc-members:
:show-inheritance:
:mod:`topos` Module
-------------------
@@ -86,6 +94,7 @@ Subpackages
.. toctree::
zipline.finance
zipline.test
zipline.transforms
+35 -3
View File
@@ -9,10 +9,18 @@ test Package
:undoc-members:
:show-inheritance:
:mod:`test_devsimulator` Module
-------------------------------
:mod:`factory` Module
---------------------
.. automodule:: zipline.test.test_devsimulator
.. automodule:: zipline.test.factory
:members:
:undoc-members:
:show-inheritance:
:mod:`test_finance` Module
--------------------------
.. automodule:: zipline.test.test_finance
:members:
:undoc-members:
:show-inheritance:
@@ -33,6 +41,22 @@ test Package
:undoc-members:
:show-inheritance:
:mod:`test_perf_tracking` Module
--------------------------------
.. automodule:: zipline.test.test_perf_tracking
:members:
:undoc-members:
:show-inheritance:
:mod:`test_risk` Module
-----------------------
.. automodule:: zipline.test.test_risk
:members:
:undoc-members:
:show-inheritance:
:mod:`test_sanity` Module
-------------------------
@@ -41,3 +65,11 @@ test Package
:undoc-members:
:show-inheritance:
:mod:`transform` Module
-----------------------
.. automodule:: zipline.test.transform
:members:
:undoc-members:
:show-inheritance:
+210 -56
View File
@@ -40,37 +40,131 @@ class PerformanceTracker():
starting_cash = capital_base
)
def to_dict(self):
"""
Creates a dictionary representing the state of this tracker.
Returns a dict object of the form:
def update(self, event):
self.event_count += 1
if(event.dt >= self.market_close):
self.handle_market_close()
+-----------------+----------------------------------------------------+
| key | value |
+=================+====================================================+
| period_start | The beginning of the period to be tracked. datetime|
| | in pytz.utc timezone. Will always be 0:00 on the |
| | date in UTC. The fact that the time may be on the |
| | prior day in the exchange's local time is ignored |
+-----------------+----------------------------------------------------+
| period_end | The end of the period to be tracked. datetime |
| | in pytz.utc timezone. Will always be 23:59 on the |
| | date in UTC. The fact that the time may be on the |
| | next day in the exchange's local time is ignored |
+-----------------+----------------------------------------------------+
| progress | percentage of test completed |
+-----------------+----------------------------------------------------+
| cumulative_capti| The net capital used (positive is spent) through |
| al_used | the course of all the events sent to this tracker |
+-----------------+----------------------------------------------------+
| max_capital_used| The maximum amount of capital deployed through the |
| | course of all the events sent to this tracker |
+-----------------+----------------------------------------------------+
| last_close | The most recent close of the market. datetime in |
| | pytz.utc timezone. Will always be 23:59 on the |
| | date in UTC. The fact that the time may be on the |
| | next day in the exchange's local time is ignored |
+-----------------+----------------------------------------------------+
| last_open | The most recent open of the market. datetime in |
| | pytz.utc timezone. Will always be 00:00 on the |
| | date in UTC. The fact that the time may be on the |
| | next day in the exchange's local time is ignored |
+-----------------+----------------------------------------------------+
| capital_base | The initial capital assumed for this tracker. |
+-----------------+----------------------------------------------------+
| returns | List of dicts representing daily returns. See the |
| | comments for |
| | :py:meth:`zipline.finance.risk.DailyReturn.to_dict`|
+-----------------+----------------------------------------------------+
| cumulative_perf | A dictionary representing the cumulative |
| | performance through all the events delivered to |
| | this tracker. For details see the comments on |
| | :py:meth:`PerformancePeriod.to_dict` |
+-----------------+----------------------------------------------------+
| todays_perf | A dictionary representing the cumulative |
| | performance through all the events delivered to |
| | this tracker with datetime stamps between last_open|
| | and last_close. For details see the comments on |
| | :py:meth:`PerformancePeriod.to_dict` |
| | TODO: adding this because we calculate it. May be |
| | overkill. |
+-----------------+----------------------------------------------------+
| cumulative_risk | A dictionary representing the risk metrics |
| _metrics | calculated based on the positions aggregated |
| | through all the events delivered to this tracker. |
| | For details look at the comments for |
| | :py:meth:`zipline.finance.risk.RiskMetrics.to_dict`|
+-----------------+----------------------------------------------------+
"""
returns_list = [x.to_dict() for x in self.returns]
d = {
'period_start' : self.period_start,
'period_end' : self.period_end,
'progress' : self.progress,
'cumulative_captial_used' : self.cumulative_captial_used,
'max_capital_used' : self.max_capital_used,
'last_close' : self.market_close,
'last_open' : self.market_open,
'capital_base' : self.capital_base,
'returns' : returns_list,
'cumulative_perf' : self.cumulative_perf.to_dict(),
'todays_perf' : self.todays_perf.to_dict(),
'cumulative_risk_metrics' : self.cumulative_risk_metrics.to_dict()
}
def update(self, event_frame):
for dt, event_series in event_frame.iteritems():
self.process_event(event_series)
def process_event(self, event):
qutil.LOGGER.debug("series is " + str(event))
self.event_count += 1
if(event.dt >= self.market_close):
self.handle_market_close()
if event.TRANSACTION != None:
self.txn_count += 1
self.cumulative_performance.execute_transaction(event.TRANSACTION)
self.todays_performance.execute_transaction(event.TRANSACTION)
if event.TRANSACTION != None:
self.txn_count += 1
self.cumulative_performance.execute_transaction(event.TRANSACTION)
self.todays_performance.execute_transaction(event.TRANSACTION)
#we're adding a 10% cushion to the capital used, and then rounding to the nearest 5k
self.cumulative_capital_used += event.TRANSACTION.price * event.TRANSACTION.amount
if(math.fabs(self.cumulative_capital_used) > self.max_capital_used):
self.max_capital_used = math.fabs(self.cumulative_capital_used)
self.max_capital_used = self.round_to_nearest(1.1 * self.max_capital_used, base=5000)
self.max_leverage = self.max_capital_used/self.capital_base
# we're adding a 10% cushion to the capital used,
# and then rounding to the nearest 5k
transaction_cost = event.TRANSACTION.price * event.TRANSACTION.amount
self.cumulative_capital_used += transaction_cost
if(math.fabs(self.cumulative_capital_used) > self.max_capital_used):
self.max_capital_used = math.fabs(self.cumulative_capital_used)
#update last sale
self.cumulative_performance.update_last_sale(event)
self.todays_performance.update_last_sale(event)
#calculate performance as of last trade
self.cumulative_performance.calculate_performance()
self.todays_performance.calculate_performance()
cushioned_capital = 1.1 * self.max_capital_used
self.max_capital_used = self.round_to_nearest(
cushioned_capital,
base=5000
)
self.max_leverage = self.max_capital_used/self.capital_base
#update last sale
self.cumulative_performance.update_last_sale(event)
self.todays_performance.update_last_sale(event)
#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 daily return 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_return_obj = risk.daily_return(todays_date, self.todays_performance.returns)
todays_return_obj = risk.DailyReturn(
todays_date,
self.todays_performance.returns
)
self.returns.append(todays_return_obj)
#calculate risk metrics for cumulative performance
@@ -92,14 +186,10 @@ class PerformanceTracker():
#calculate progress of test
self.progress = self.day_count / self.total_days
######################################################################################################
#######TODO: report/relay metrics out to qexec -- values come from self.cur_period_metrics ###########
#######TODO: report/relay position data out to qexec -- values come from self.cumulative_performance #
######################################################################################################
####################################################################
#######TODO: relay the results of self.to_dict() ###########
####################################################################
#roll over positions to current day.
self.todays_performance.calculate_performance()
@@ -115,24 +205,21 @@ class PerformanceTracker():
self.trading_environment
)
######################################################################################################
#######TODO: report/relay metrics out to qexec -- values come from self.risk_report ###########
######################################################################################################
####################################################################
#######TODO: relay the results of self.risk_report.to_dict() #######
####################################################################
def round_to_nearest(self, x, base=5):
return int(base * round(float(x)/base))
class Position():
sid = None
amount = None
cost_basis = None
last_sale = None
last_date = None
def __init__(self, sid):
self.sid = sid
self.amount = 0
self.cost_basis = 0.0 ##per share
self.last_sale_price = None
self.last_sale_date = None
def update(self, txn):
if(self.sid != txn.sid):
@@ -156,24 +243,53 @@ class Position():
def __repr__(self):
template = "sid: {sid}, amount: {amount}, cost_basis: {cost_basis}, \
last_sale: {last_sale}"
last_sale_price: {last_sale_price}"
return template.format(
sid=self.sid,
amount=self.amount,
cost_basis=self.cost_basis,
last_sale=self.last_sale
last_sale_price=self.last_sale_price
)
def to_dict(self):
"""
Creates a dictionary representing the state of this position.
Returns a dict object of the form:
+-----------------+----------------------------------------------------+
| key | value |
+=================+====================================================+
| sid | the identifier for the security held in this |
| | position. |
+-----------------+----------------------------------------------------+
| amount | whole number of shares in the position |
+-----------------+----------------------------------------------------+
| last_sale_price | price at last sale of the security on the exchange |
+-----------------+----------------------------------------------------+
| last_sale_date | datetime of the last trade of the position's |
| | security on the exchange |
+-----------------+----------------------------------------------------+
"""
state = {
'sid':self.sid,
'amount':self.amount,
'cost_basis':self.cost_basis,
'last_sale_price':self.last_sale_price,
'last_sale_date':self.last_sale_date
}
return state
class PerformancePeriod():
def __init__(self, initial_positions, starting_value, starting_cash):
self.ending_value = 0.0
self.period_capital_used = 0.0
self.positions = initial_positions #sid => position object
self.starting_value = starting_value
self.ending_value = 0.0
self.period_capital_used = 0.0
self.pnl = 0.0
#sid => position object
self.positions = initial_positions
self.starting_value = starting_value
#cash balance at start of period
self.starting_cash = starting_cash
self.ending_cash = starting_cash
self.starting_cash = starting_cash
self.ending_cash = starting_cash
def calculate_performance(self):
self.ending_value = self.calculate_positions_value()
@@ -194,7 +310,6 @@ class PerformancePeriod():
self.positions[txn.sid].update(txn)
self.period_capital_used += -1 * txn.price * txn.amount
def calculate_positions_value(self):
mktValue = 0.0
for key,pos in self.positions.iteritems():
@@ -202,9 +317,48 @@ class PerformancePeriod():
return mktValue
def update_last_sale(self, event):
if self.positions.has_key(event.sid) and event.type == zp.DATASOURCE_TYPE.TRADE:
self.positions[event.sid].last_sale = event.price
self.positions[event.sid].last_date = event.dt
is_trade = event.type == zp.DATASOURCE_TYPE.TRADE
if self.positions.has_key(event.sid) and is_trade:
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
Returns a dict object of the form:
+---------------+-----------------------------------------------------------+
| key | value |
+===============+===========================================================+
| ending_value | the total market value of the positions held at the |
| | end of the period |
+---------------+-----------------------------------------------------------+
| capital_used | the net capital consumed (positive means spent) by |
| | buying and selling securities in the period |
+---------------+-----------------------------------------------------------+
| starting_value| the total market value of the positions held at the |
| | start of the period |
+---------------+-----------------------------------------------------------+
| starting_cash | cash on hand at the beginning of the period |
+---------------+-----------------------------------------------------------+
| ending_cash | cash on hand at the end of the period |
+---------------+-----------------------------------------------------------+
| positions | a list of dicts representing positions, see |
| | :py:meth:`Position.to_dict()` |
| | for details on the contents of the dict |
+---------------+-----------------------------------------------------------+
"""
d = {
'ending_value':self.ending_value,
'capital_used':self.capital_used,
'starting_value':self.starting_value,
'starting_cash':self.starting_cash,
'ending_cash':self.ending_cash
}
position_list = []
for pos in self.positions:
position_list.append(pos.to_dict())
d['positions'] = positions_list
return d
+138 -42
View File
@@ -7,20 +7,25 @@ import zipline.util as qutil
import zipline.protocol as zp
from pymongo import ASCENDING, DESCENDING
class daily_return():
class DailyReturn():
def __init__(self, date, returns):
self.date = date
self.returns = returns
def to_dict(self):
d = {
'dt': self.date,
'returns': self.returns
}
return d
def __repr__(self):
return str(self.date) + " - " + str(self.returns)
class RiskMetrics():
def __init__(self, start_date, end_date, returns, trading_environment):
"""
:param treasury_curves: {datetime in utc -> {duration label -> interest rate}}
"""
self.treasury_curves = trading_environment.treasury_curves
self.start_date = start_date
@@ -31,32 +36,100 @@ class RiskMetrics():
self.benchmark_period_returns, self.benchmark_returns = self.calculate_period_returns(benchmark_returns)
if(len(self.benchmark_returns) != len(self.algorithm_returns)):
raise Exception("Mismatch between benchmark_returns ({bm_count}) and algorithm_returns ({algo_count}) in range {start} : {end}".format(
bm_count=len(self.benchmark_returns),
algo_count=len(self.algorithm_returns),
start=start_date,
end=end_date))
message = "Mismatch between benchmark_returns ({bm_count}) and \
algorithm_returns ({algo_count}) in range {start} : {end}"
message.format(
bm_count=len(self.benchmark_returns),
algo_count=len(self.algorithm_returns),
start=start_date,
end=end_date
)
raise Exception(messge)
self.trading_days = len(self.benchmark_returns)
self.benchmark_volatility = self.calculate_volatility(self.benchmark_returns)
self.algorithm_volatility = self.calculate_volatility(self.algorithm_returns)
self.treasury_period_return = self.choose_treasury()
self.sharpe = self.calculate_sharpe()
self.beta, self.algorithm_covariance, self.benchmark_variance, self.condition_number, self.eigen_values = self.calculate_beta()
self.beta, self.algorithm_covariance, self.benchmark_variance, \
self.condition_number, self.eigen_values = self.calculate_beta()
self.alpha = self.calculate_alpha()
self.excess_return = self.algorithm_period_returns - self.treasury_period_return
self.max_drawdown = self.calculate_max_drawdown()
def to_dict(self):
"""
+-----------------+----------------------------------------------------+
| key | value |
+=================+====================================================+
| trading_days | The number of trading days between self.start_date |
| | and self.end_date |
+-----------------+----------------------------------------------------+
| benchmark_volat\| The volatility of the benchmark between |
| ility | self.start_date and self.end_date. |
+-----------------+----------------------------------------------------+
| algo_volatility | The volatility of the algo between self.start_date |
| | and self.end_date. |
+-----------------+----------------------------------------------------+
| treasury_period\| The return of treasuries over the period. Treasury |
| _return | maturity is chosen to match the duration of the |
| | test period. |
+-----------------+----------------------------------------------------+
| sharpe | The sharpe ratio based on the _algorithm_ (rather |
| | than the static portfolio) returns. |
+-----------------+----------------------------------------------------+
| beta | The _algorithm_ beta to the benchmark. |
+-----------------+----------------------------------------------------+
| alpha | The _algorithm_ alpha to the benchmark. |
+-----------------+----------------------------------------------------+
| excess_return | The excess return of the algorithm over the |
| | benchmark. |
+-----------------+----------------------------------------------------+
| max_drawdown | The largest relative peak to relative trough move |
| | for the portfolio returns between self.start_date |
| | and self.end_date. |
+-----------------+----------------------------------------------------+
"""
d = {
'trading_days' : self.trading_days,
'benchmark_volatility' : self.benchmark_volatility,
'algo_volatility' : self.algo_volatility,
'treasury_period_return': self.treasury_period_return,
'sharpe' : self.sharpe,
'beta' : self.beta,
'alpha' : self.alpha,
'excess_return' : self.excess_return,
'max_drawdown' : self.max_drawdown
}
def __repr__(self):
statements = []
for metric in ["algorithm_period_returns", "benchmark_period_returns", "excess_return", "trading_days", "benchmark_volatility", "algorithm_volatility", "sharpe", "algorithm_covariance", "benchmark_variance", "beta", "alpha", "max_drawdown", "algorithm_returns", "benchmark_returns", "condition_number", "eigen_values"]:
for metric in [
"algorithm_period_returns",
"benchmark_period_returns",
"excess_return",
"trading_days",
"benchmark_volatility",
"algorithm_volatility",
"sharpe",
"algorithm_covariance",
"benchmark_variance",
"beta",
"alpha",
"max_drawdown",
"algorithm_returns",
"benchmark_returns",
"condition_number",
"eigen_values"
]:
value = getattr(self, metric)
statements.append("{metric}:{value}".format(metric=metric, value=value))
statements.append("{m}:{v}".format(m=metric, v=value))
return '\n'.join(statements)
def calculate_period_returns(self, daily_returns):
#TODO: replace this with pandas.
returns = [x.returns for x in daily_returns if x.date >= self.start_date and x.date <= self.end_date and self.trading_environment.is_trading_day(x.date)]
#qutil.LOGGER.debug("using {count} daily returns out of {total}".format(count=len(returns),total=len(daily_returns)))
period_returns = 1.0
for r in returns:
period_returns = period_returns * (1.0 + r)
@@ -71,8 +144,8 @@ class RiskMetrics():
return (self.algorithm_period_returns - self.treasury_period_return) / self.algorithm_volatility
def calculate_beta(self):
#qutil.LOGGER.debug("algorithm has {acount} days, benchmark has {bmcount} days".format(acount=len(self.algorithm_returns), bmcount=len(self.benchmark_returns)))
#it doesn't make much sense to calculate beta for less than two days, so return none.
#it doesn't make much sense to calculate beta for less than two days,
#so return none.
if len(self.algorithm_returns) < 2:
return 0.0, 0.0, 0.0, 0.0, []
returns_matrix = np.vstack([self.algorithm_returns, self.benchmark_returns])
@@ -82,7 +155,6 @@ class RiskMetrics():
algorithm_covariance = C[0][1]
benchmark_variance = C[1][1]
beta = C[0][1] / C[1][1]
#qutil.LOGGER.debug("bm variance is {bmv}, returns matrix is {rm}, covariance is {c}, beta is {beta}".format(rm=returns_matrix, bmv=C[1][1], c=C, beta=beta))
return beta, algorithm_covariance, benchmark_variance, condition_number, eigen_values
@@ -101,7 +173,6 @@ class RiskMetrics():
cur_return = 0.0
compounded_returns.append(cur_return)
#qutil.LOGGER.debug("compounded returns are {cr}".format(cr=compounded_returns))
cur_max = None
max_drawdown = None
for cur in compounded_returns:
@@ -112,7 +183,6 @@ class RiskMetrics():
if max_drawdown == None or drawdown < max_drawdown:
max_drawdown = drawdown
#qutil.LOGGER.debug("max drawdown is: {dd}".format(dd=max_drawdown))
if max_drawdown == None:
return 0.0
@@ -146,10 +216,10 @@ class RiskMetrics():
one_day = datetime.timedelta(days=1)
curve = None
#in case end date is not a trading day, search for the next market day for an interest rate
# in case end date is not a trading day, search for the next market
# day for an interest rate
for i in range(7):
if(self.treasury_curves.has_key(self.end_date + i * one_day)):
#qutil.LOGGER.info(self.treasury_curves[self.end_date + i * one_day])
curve = self.treasury_curves[self.end_date + i * one_day]
break
@@ -162,38 +232,58 @@ class RiskMetrics():
if rate != None:
return rate * (td.days + 1) / 365
raise Exception("no rate for end date = {dt} and term = {term}. Using zero.".format(dt=self.end_date,
term=self.treasury_duration))
message = "no rate for end date = {dt} and term = {term}. Using zero."
message = message.format(dt=self.end_date,term=self.treasury_duration)
raise Exception(message)
class RiskReport():
def __init__(self, algorithm_returns, benchmark_returns, treasury_curves, trading_environment):
"""algorithm_returns needs to be a list of daily_return objects sorted in date ascending order"""
def __init__(self, algorithm_returns, trading_environment):
""" algorithm_returns needs to be a list of daily_return objects
sorted in date ascending order
"""
self.algorithm_returns = algorithm_returns
self.treasury_curves = treasury_curves
self.trading_environment = trading_environment
start_date = self.algorithm_returns[0].date
end_date = self.algorithm_returns[-1].date
self.month_periods = self.periodsInRange(1, start_date, end_date)
self.three_month_periods = self.periodsInRange(3, start_date, end_date)
self.six_month_periods = self.periodsInRange(6, start_date, end_date)
self.year_periods = self.periodsInRange(12, start_date, end_date)
#calculate month ends
self.month_periods = self.periodsInRange(1, self.algorithm_returns[0].date, self.algorithm_returns[-1].date)
#calculate 3 month ends
self.three_month_periods = self.periodsInRange(3, self.algorithm_returns[0].date, self.algorithm_returns[-1].date)
#calculate 6 month ends
self.six_month_periods = self.periodsInRange(6, self.algorithm_returns[0].date, self.algorithm_returns[-1].date)
#calculate 1 year ends
self.year_periods = self.periodsInRange(12, self.algorithm_returns[0].date, self.algorithm_returns[-1].date)
#calculate 3 year ends
self.three_year_periods = self.periodsInRange(36, self.algorithm_returns[0].date, self.algorithm_returns[-1].date)
#calculate 5 year ends
self.five_year_periods = self.periodsInRange(60, self.algorithm_returns[0].date, self.algorithm_returns[-1].date)
def to_dict(self):
"""
RiskMetrics are calculated for rolling windows in four lengths::
- 1_month
- 3_month
- 6_month
- 12_month
The return value of this funciton is a dictionary keyed by the above
list of durations. The value of each entry is a list of RiskMetric
dicts of the same duration as denoted by the top_level key.
See :py:meth:`RiskMetrics.to_dict` for the detailed list of fields
provided for each period.
"""
d = {
'1_month' : [x.to_dict() for x in self.month_periods],
'3_month' : [x.to_dict() for x in self.three_year_periods],
'6_month' : [x.to_dict() for x in self.six_month_periods],
'12_month' : [x.to_dict() for x in self.month_periods]
}
return d
def periodsInRange(self, months_per, start, end):
one_day = datetime.timedelta(days = 1)
ends = []
cur_start = start.replace(day=1)
#ensure that we have an end at the end of a calendar month, in case the return series ends mid-month...
#ensure that we have an end at the end of a calendar month, in case
#the return series ends mid-month...
the_end = advance_by_months(end.replace(day=1),1) - one_day
while True:
cur_end = advance_by_months(cur_start, months_per) - one_day
@@ -223,9 +313,10 @@ def advance_by_months(dt, jump_in_months):
years = month / 12
month = month % 12
#no remainder means that we are landing in december.
#modulo is, in a way, a zero indexed circular array.
#this is a way of converting to 1 indexed months. (in our modulo index, december is zeroth)
# no remainder means that we are landing in december.
# modulo is, in a way, a zero indexed circular array.
# this is a way of converting to 1 indexed months.
# (in our modulo index, december is zeroth)
if(month == 0):
month = 12
years = years - 1
@@ -245,7 +336,12 @@ class TradingEnvironment(object):
self.trading_day_map[bm.date] = bm
def normalize_date(self, test_date):
return datetime.datetime(year=test_date.year, month=test_date.month, day=test_date.day, tzinfo=pytz.utc)
return datetime.datetime(
year=test_date.year,
month=test_date.month,
day=test_date.day,
tzinfo=pytz.utc
)
def is_trading_day(self, test_date):
dt = self.normalize_date(test_date)
+14 -10
View File
@@ -15,7 +15,7 @@ class TradeSimulationClient(qmsg.Component):
qmsg.Component.__init__(self)
self.received_count = 0
self.prev_dt = None
self.event_queue = []
self.event_queue = None
self.event_callbacks = []
self.txn_count = 0
self.current_dt = simulation_dt
@@ -60,12 +60,10 @@ class TradeSimulationClient(qmsg.Component):
if event.source_id != zp.FINANCE_COMPONENT.ORDER_SOURCE:
#mark the start time for client's processing of this event.
event_start = datetime.datetime.utcnow()
self.queue_event(event)
for cb in self.event_callbacks:
if(event.dt < self.current_dt):
self.queue_event(event)
else:
cb(self.event_frame)
if(event.dt >= self.current_dt):
cb(self.get_frame())
#update time based on receipt of the order
self.last_iteration_duration = datetime.datetime.utcnow() - event_start
@@ -90,10 +88,16 @@ class TradeSimulationClient(qmsg.Component):
def signal_order_done(self):
self.order_socket.send(str(zp.ORDER_PROTOCOL.DONE))
def frame_event(self, event):
if self.event_frame == None:
self.event_frame = pandas.DataFrame()
self.event_frame.append(event)
def queue_event(self, event):
if self.event_queue == None:
self.event_queue = {}
self.event_queue[event.dt] = event.as_series()
def get_frame(self):
sorted_dates = sorted(self.event_queue.keys())
frame = pandas.DataFrame(self.event_queue, index=sorted_dates)
self.event_queue = None
return frame
class OrderDataSource(qmsg.DataSource):
"""DataSource that relays orders from the client"""
+2 -1
View File
@@ -208,7 +208,8 @@ class namedict(object):
return self.__dict__.has_key(name)
def as_series(self):
s = pandas.Series(self.values(), self.keys())
s = pandas.Series(self.__dict__.values(), self.__dict__.keys())
return s
# ================
# Control Protocol
+4 -4
View File
@@ -19,7 +19,7 @@ def load_market_data():
tzinfo=pytz.utc
)
daily_return = risk.daily_return(date=event_dt, returns=returns)
daily_return = risk.DailyReturn(date=event_dt, returns=returns)
bm_returns.append(daily_return)
bm_returns = sorted(bm_returns, key=lambda(x): x.date)
fp_tr = open("./zipline/test/treasury_curves.msgpack", "rb")
@@ -93,7 +93,7 @@ def create_returns(daycount, start, trading_calendar):
one_day = datetime.timedelta(days = 1)
while i < daycount:
i += 1
r = risk.daily_return(current, random.random())
r = risk.DailyReturn(current, random.random())
test_range.append(r)
current = current + one_day
return [ x for x in test_range if(trading_calendar.is_trading_day(x.date)) ]
@@ -109,7 +109,7 @@ def create_returns_from_range(start, end, trading_calendar):
current = current + one_day
if(not trading_calendar.is_trading_day(current)):
continue
r = risk.daily_return(current, random.random())
r = risk.DailyReturn(current, random.random())
i += 1
test_range.append(r)
@@ -122,7 +122,7 @@ def create_returns_from_list(returns, start, trading_calendar):
i = 0
while len(test_range) < len(returns):
if(trading_calendar.is_trading_day(current)):
r = risk.daily_return(current, returns[i])
r = risk.DailyReturn(current, returns[i])
i += 1
test_range.append(r)
current = current + one_day