mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-13 17:10:00 +08:00
TST: Update to empyrical, increase test coverage
ENH: Resolve rebase conflict by using updated example_data.tar TST: Increase test coverage for risk portion of zipline
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"%PYTHON%" setup.py install
|
||||
"%PYTHON%" setup.py install
|
||||
if errorlevel 1 exit 1
|
||||
|
||||
:: Add more build steps here, if they are necessary.
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
$PYTHON setup.py install
|
||||
$PYTHON setup.py install
|
||||
|
||||
# Add more build steps here, if they are necessary.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package:
|
||||
name: empyrical
|
||||
version: "0.1.9"
|
||||
|
||||
source:
|
||||
fn: empyrical-0.1.9.tar.gz
|
||||
url: https://pypi.python.org/packages/15/6b/de1d277d4342d2cecc8134f4935248853f32299cdd9b01728b0ec420c350/empyrical-0.1.9.tar.gz
|
||||
md5: 2c8b928cae192fc9cb8b7104608eec56
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- python
|
||||
- setuptools
|
||||
- numpy x.x
|
||||
- pandas >=0.16.1
|
||||
- scipy >=0.15.1
|
||||
- bottleneck >=1.0.0
|
||||
|
||||
run:
|
||||
- python
|
||||
- numpy x.x
|
||||
- pandas >=0.16.1
|
||||
- scipy >=0.15.1
|
||||
- bottleneck >=1.0.0
|
||||
|
||||
about:
|
||||
home: https://github.com/quantopian/empyrical
|
||||
license: Apache Software License
|
||||
summary: 'empyrical is a Python library with performance and risk statistics\ncommonly used in quantitative finance'
|
||||
|
||||
# See
|
||||
# http://docs.continuum.io/conda/build.html for
|
||||
# more information about meta.yaml
|
||||
@@ -1,27 +0,0 @@
|
||||
package:
|
||||
name: qrisk
|
||||
version: "0.1.4"
|
||||
|
||||
source:
|
||||
fn: qrisk-0.1.4.tar.gz
|
||||
url: https://files.pythonhosted.org/packages/49/c9/81924d56e8173c4e92d60f5e59143dd345a0bf015508f85683ed9c2efd27/qrisk-0.1.4.tar.gz
|
||||
md5: 24a76bcb960e82ade86bf115e87c5f53
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- python
|
||||
- setuptools
|
||||
- numpy x.x
|
||||
- pandas >=0.16.1
|
||||
- scipy >=0.15.1
|
||||
|
||||
run:
|
||||
- python
|
||||
- numpy x.x
|
||||
- pandas >=0.16.1
|
||||
- scipy >=0.15.1
|
||||
|
||||
about:
|
||||
home: https://github.com/quantopian/qrisk
|
||||
license: Apache Software License
|
||||
summary: 'qrisk is a Python library with performance and risk statistics\ncommonly used in quantitative finance'
|
||||
@@ -64,4 +64,4 @@ intervaltree==2.1.0
|
||||
cachetools==1.1.5
|
||||
|
||||
# For financial risk calculations
|
||||
qrisk==0.1.4
|
||||
empyrical>=0.1.9
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+1
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
||||
{"names": ["open", "high", "low", "close", "volume", "day", "id"]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{}
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
{"nbytes": 98584, "shape": [24646], "cbytes": 131072}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"chunklen": 32768, "dtype": "uint32", "expectedlen": 24646, "dflt": 0, "cparams": {"shuffle": true, "clevel": 5}}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{}
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
{"nbytes": 98584, "shape": [24646], "cbytes": 131072}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"chunklen": 32768, "dtype": "uint32", "expectedlen": 24646, "dflt": 0, "cparams": {"shuffle": true, "clevel": 5}}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{}
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
{"nbytes": 98584, "shape": [24646], "cbytes": 131072}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"chunklen": 32768, "dtype": "uint32", "expectedlen": 24646, "dflt": 0, "cparams": {"shuffle": true, "clevel": 5}}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{}
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
{"nbytes": 98584, "shape": [24646], "cbytes": 131072}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"chunklen": 32768, "dtype": "uint32", "expectedlen": 24646, "dflt": 0, "cparams": {"shuffle": true, "clevel": 5}}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{}
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
{"nbytes": 98584, "shape": [24646], "cbytes": 131072}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"chunklen": 32768, "dtype": "uint32", "expectedlen": 24646, "dflt": 0, "cparams": {"shuffle": true, "clevel": 5}}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{}
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
{"nbytes": 98584, "shape": [24646], "cbytes": 131072}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"chunklen": 32768, "dtype": "uint32", "expectedlen": 24646, "dflt": 0, "cparams": {"shuffle": true, "clevel": 5}}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{}
|
||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
||||
{"nbytes": 98584, "shape": [24646], "cbytes": 131072}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"chunklen": 32768, "dtype": "uint32", "expectedlen": 24646, "dflt": 0, "cparams": {"shuffle": true, "clevel": 5}}
|
||||
+1
File diff suppressed because one or more lines are too long
@@ -17,15 +17,11 @@ import numpy as np
|
||||
import pandas as pd
|
||||
import zipline.finance.risk as risk
|
||||
from zipline.utils import factory
|
||||
import pandas as pd
|
||||
|
||||
from zipline.testing.fixtures import WithTradingEnvironment, ZiplineTestCase
|
||||
|
||||
from zipline.finance.trading import SimulationParameters
|
||||
|
||||
from . import answer_key
|
||||
ANSWER_KEY = answer_key.ANSWER_KEY
|
||||
|
||||
RETURNS_BASE = 0.01
|
||||
RETURNS = [RETURNS_BASE] * 251
|
||||
|
||||
@@ -38,16 +34,10 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
|
||||
def init_instance_fixtures(self):
|
||||
super(TestRisk, self).init_instance_fixtures()
|
||||
<<<<<<< 30f5a8fcfa4a194f05d58f50cf0a2b06dd8085cc
|
||||
|
||||
|
||||
start_session = pd.Timestamp("2006-01-01", tz='UTC')
|
||||
end_session = pd.Timestamp("2006-12-29", tz='UTC')
|
||||
|
||||
=======
|
||||
start_date = pd.Timestamp('2006-01-01', tz=pytz.utc)
|
||||
end_date = pd.Timestamp('2006-12-29', tz=pytz.utc)
|
||||
>>>>>>> ENH: Change datetime.datetime to pd.Timestamp in tests
|
||||
self.sim_params = SimulationParameters(
|
||||
start_session=start_session,
|
||||
end_session=end_session,
|
||||
@@ -150,3 +140,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
all(isinstance(x, float)
|
||||
for x in self.cumulative_metrics.max_drawdowns),
|
||||
True)
|
||||
|
||||
def test_representation(self):
|
||||
assert all([metric in self.cumulative_metrics.__repr__() for metric in
|
||||
self.cumulative_metrics.METRIC_NAMES])
|
||||
|
||||
+147
-72
@@ -17,8 +17,6 @@ import datetime
|
||||
import calendar
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import pytz
|
||||
import pandas as pd
|
||||
|
||||
import zipline.finance.risk as risk
|
||||
from zipline.utils import factory
|
||||
@@ -26,6 +24,8 @@ from zipline.utils import factory
|
||||
from zipline.finance.trading import SimulationParameters
|
||||
from zipline.testing.fixtures import WithTradingEnvironment, ZiplineTestCase
|
||||
|
||||
from zipline.finance.risk.period import RiskMetricsPeriod
|
||||
|
||||
RETURNS_BASE = 0.01
|
||||
RETURNS = [RETURNS_BASE] * 251
|
||||
|
||||
@@ -38,17 +38,14 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
|
||||
def init_instance_fixtures(self):
|
||||
super(TestRisk, self).init_instance_fixtures()
|
||||
|
||||
start_session = pd.Timestamp("2006-01-01", tz='UTC')
|
||||
|
||||
end_session = self.trading_calendar.minute_to_session_label(
|
||||
self.start_session = pd.Timestamp("2006-01-01", tz='UTC')
|
||||
self.end_session = self.trading_calendar.minute_to_session_label(
|
||||
pd.Timestamp("2006-12-31", tz='UTC'),
|
||||
direction="previous"
|
||||
)
|
||||
|
||||
self.sim_params = SimulationParameters(
|
||||
start_session=start_session,
|
||||
end_session=end_session,
|
||||
start_session=self.start_session,
|
||||
end_session=self.end_session,
|
||||
trading_calendar=self.trading_calendar,
|
||||
)
|
||||
self.algo_returns = factory.create_returns_from_list(
|
||||
@@ -63,16 +60,15 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
self.algo_returns,
|
||||
self.sim_params,
|
||||
benchmark_returns=self.benchmark_returns,
|
||||
trading_schedule=self.trading_schedule,
|
||||
trading_calendar=self.trading_calendar,
|
||||
treasury_curves=self.env.treasury_curves,
|
||||
)
|
||||
|
||||
def test_factory(self):
|
||||
returns = [0.1] * 100
|
||||
r_objects = factory.create_returns_from_list(returns, self.sim_params)
|
||||
self.assertTrue(r_objects.index[-1] <= self.end_date)
|
||||
self.assertTrue(r_objects.index[0] >= self.start_date)
|
||||
self.assertTrue(r_objects.sample().values[0] == 0.1)
|
||||
self.assertTrue(r_objects.index[-1] <=
|
||||
pd.Timestamp('2006-12-31', tz='UTC'))
|
||||
|
||||
def test_drawdown(self):
|
||||
np.testing.assert_equal(
|
||||
@@ -123,7 +119,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
[20, 19, 23, 19, 22, 22, 20, 23, 20, 22, 21, 20])
|
||||
|
||||
def test_benchmark_volatility(self):
|
||||
# Volatility is calculated by a qrisk function so testing
|
||||
# Volatility is calculated by a empyrical function so testing
|
||||
# of period volatility will be limited to determine if the value is
|
||||
# numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
@@ -170,7 +166,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
DECIMAL_PLACES)
|
||||
|
||||
def test_algorithm_volatility(self):
|
||||
# Volatility is calculated by a qrisk function so testing
|
||||
# Volatility is calculated by a empyrical function so testing
|
||||
# of period volatility will be limited to determine if the value is
|
||||
# numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
@@ -191,7 +187,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
True)
|
||||
|
||||
def test_algorithm_sharpe(self):
|
||||
# The sharpe ratio is calculated by a qrisk function so testing
|
||||
# The sharpe ratio is calculated by a empyrical function so testing
|
||||
# of period sharpe ratios will be limited to determine if the value is
|
||||
# numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
@@ -212,7 +208,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
True)
|
||||
|
||||
def test_algorithm_downside_risk(self):
|
||||
# Downside risk is calculated by a qrisk function so testing
|
||||
# Downside risk is calculated by a empyrical function so testing
|
||||
# of period downside risk will be limited to determine if the value is
|
||||
# numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
@@ -233,7 +229,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
True)
|
||||
|
||||
def test_algorithm_sortino(self):
|
||||
# The sortino ratio is calculated by a qrisk function so testing
|
||||
# The sortino ratio is calculated by a empyrical function so testing
|
||||
# of period sortino ratios will be limited to determine if the value is
|
||||
# numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
@@ -254,9 +250,9 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
True)
|
||||
|
||||
def test_algorithm_information(self):
|
||||
# The information ratio is calculated by a qrisk function so testing
|
||||
# of period information ratio will be limited to determine if the value
|
||||
# is numerical. This tests for its existence and format.
|
||||
# The information ratio is calculated by a empyrical function
|
||||
# testing of period information ratio will be limited to determine
|
||||
# if the value is numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
all(isinstance(x.information, float)
|
||||
for x in self.metrics.month_periods),
|
||||
@@ -275,7 +271,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
True)
|
||||
|
||||
def test_algorithm_beta(self):
|
||||
# Beta is calculated by a qrisk function so testing
|
||||
# Beta is calculated by a empyrical function so testing
|
||||
# of period beta will be limited to determine if the value is
|
||||
# numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
@@ -296,7 +292,7 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
True)
|
||||
|
||||
def test_algorithm_alpha(self):
|
||||
# Alpha is calculated by a qrisk function so testing
|
||||
# Alpha is calculated by a empyrical function so testing
|
||||
# of period alpha will be limited to determine if the value is
|
||||
# numerical. This tests for its existence and format.
|
||||
np.testing.assert_equal(
|
||||
@@ -316,49 +312,6 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
for x in self.metrics.year_periods),
|
||||
True)
|
||||
|
||||
def test_algorithm_covariance(self):
|
||||
np.testing.assert_almost_equal(
|
||||
[x.algorithm_covariance for x in self.metrics.month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
DECIMAL_PLACES)
|
||||
np.testing.assert_almost_equal(
|
||||
[x.algorithm_covariance
|
||||
for x in self.metrics.three_month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
DECIMAL_PLACES)
|
||||
np.testing.assert_almost_equal(
|
||||
[x.algorithm_covariance
|
||||
for x in self.metrics.six_month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
DECIMAL_PLACES)
|
||||
np.testing.assert_almost_equal(
|
||||
[x.algorithm_covariance
|
||||
for x in self.metrics.year_periods],
|
||||
[0.0],
|
||||
DECIMAL_PLACES)
|
||||
|
||||
def test_benchmark_variance(self):
|
||||
np.testing.assert_almost_equal(
|
||||
[x.benchmark_variance
|
||||
for x in self.metrics.month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
DECIMAL_PLACES)
|
||||
np.testing.assert_almost_equal(
|
||||
[x.benchmark_variance
|
||||
for x in self.metrics.three_month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
DECIMAL_PLACES)
|
||||
np.testing.assert_almost_equal(
|
||||
[x.benchmark_variance
|
||||
for x in self.metrics.six_month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
DECIMAL_PLACES)
|
||||
np.testing.assert_almost_equal(
|
||||
[x.benchmark_variance
|
||||
for x in self.metrics.year_periods],
|
||||
[0.0],
|
||||
DECIMAL_PLACES)
|
||||
|
||||
def test_treasury_returns(self):
|
||||
returns = factory.create_returns_from_range(self.sim_params)
|
||||
metrics = risk.RiskReport(returns, self.sim_params,
|
||||
@@ -407,13 +360,33 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
[0.0500])
|
||||
|
||||
def test_benchmarkrange(self):
|
||||
self.check_year_range(
|
||||
pd.Timestamp('2008-01-01', tz=pytz.utc),
|
||||
2)
|
||||
start_session = self.trading_calendar.minute_to_session_label(
|
||||
pd.Timestamp("2008-01-01", tz='UTC')
|
||||
)
|
||||
|
||||
end_session = self.trading_calendar.minute_to_session_label(
|
||||
pd.Timestamp("2010-01-01", tz='UTC'), direction="previous"
|
||||
)
|
||||
|
||||
sim_params = SimulationParameters(
|
||||
start_session=start_session,
|
||||
end_session=end_session,
|
||||
trading_calendar=self.trading_calendar,
|
||||
)
|
||||
|
||||
returns = factory.create_returns_from_range(sim_params)
|
||||
metrics = risk.RiskReport(returns, self.sim_params,
|
||||
trading_calendar=self.trading_calendar,
|
||||
treasury_curves=self.env.treasury_curves,
|
||||
benchmark_returns=self.env.benchmark_returns)
|
||||
|
||||
self.check_metrics(metrics, 24, start_session)
|
||||
|
||||
def test_partial_month(self):
|
||||
|
||||
start = pd.Timestamp('1991-01-01', tz=pytz.utc)
|
||||
start_session = self.trading_calendar.minute_to_session_label(
|
||||
pd.Timestamp("1991-01-01", tz='UTC')
|
||||
)
|
||||
|
||||
# 1992 and 1996 were leap years
|
||||
total_days = 365 * 5 + 2
|
||||
@@ -504,6 +477,108 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
|
||||
end=col[-1]._end_session,
|
||||
actual=len(col))
|
||||
)
|
||||
self.assert_month(start_date.month, col[-1]._end_session.month)
|
||||
self.assert_last_day(col[-1]._end_session)
|
||||
|
||||
self.assert_month(start_date.month, col[-1].end_date.month)
|
||||
self.assert_last_day(col[-1].end_date)
|
||||
def test_algorithm_leverages(self):
|
||||
# Max leverage for an algorithm with 'None' as leverage is 0.
|
||||
np.testing.assert_equal(
|
||||
[x.max_leverage for x in self.metrics.month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
|
||||
np.testing.assert_equal(
|
||||
[x.max_leverage for x in self.metrics.three_month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
|
||||
np.testing.assert_equal(
|
||||
[x.max_leverage for x in self.metrics.six_month_periods],
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
|
||||
np.testing.assert_equal(
|
||||
[x.max_leverage for x in self.metrics.year_periods],
|
||||
[0.0])
|
||||
|
||||
def test_returns_beyond_treasury(self):
|
||||
# The last treasury value is used when return dates go beyond
|
||||
# treasury curve data
|
||||
treasury_curves = self.env.treasury_curves
|
||||
treasury = treasury_curves[treasury_curves.index < self.start_session]
|
||||
|
||||
test_period = RiskMetricsPeriod(
|
||||
start_session=self.start_session,
|
||||
end_session=self.end_session,
|
||||
returns=self.algo_returns,
|
||||
benchmark_returns=self.benchmark_returns,
|
||||
trading_calendar=self.trading_calendar,
|
||||
treasury_curves=treasury,
|
||||
algorithm_leverages=[.01, .02, .03]
|
||||
)
|
||||
assert test_period.treasury_curves.equals(treasury[-1:])
|
||||
# This return period has a list instead of None for algorithm_leverages
|
||||
# Confirm that max_leverage is set to the max of those values
|
||||
assert test_period.max_leverage == .03
|
||||
|
||||
def test_index_mismatch_exception(self):
|
||||
# An exception is raised when returns and benchmark returns
|
||||
# have indexes that do not match
|
||||
bench_params = SimulationParameters(
|
||||
start_session=pd.Timestamp("2006-02-01", tz='UTC'),
|
||||
end_session=pd.Timestamp("2006-02-28", tz='UTC'),
|
||||
trading_calendar=self.trading_calendar,
|
||||
)
|
||||
benchmark = factory.create_returns_from_list(
|
||||
[BENCHMARK_BASE]*19,
|
||||
bench_params
|
||||
)
|
||||
with np.testing.assert_raises(Exception):
|
||||
RiskMetricsPeriod(
|
||||
start_session=self.start_session,
|
||||
end_session=self.end_session,
|
||||
returns=self.algo_returns,
|
||||
benchmark_returns=benchmark,
|
||||
trading_calendar=self.trading_calendar,
|
||||
treasury_curves=self.env.treasury_curves,
|
||||
)
|
||||
|
||||
def test_sharpe_value_when_null(self):
|
||||
# Sharpe is displayed as '0.0' instead of np.nan
|
||||
null_returns = factory.create_returns_from_list(
|
||||
[0.0]*251,
|
||||
self.sim_params
|
||||
)
|
||||
test_period = RiskMetricsPeriod(
|
||||
start_session=self.start_session,
|
||||
end_session=self.end_session,
|
||||
returns=null_returns,
|
||||
benchmark_returns=self.benchmark_returns,
|
||||
trading_calendar=self.trading_calendar,
|
||||
treasury_curves=self.env.treasury_curves,
|
||||
)
|
||||
assert test_period.sharpe == 0.0
|
||||
|
||||
def test_representation(self):
|
||||
test_period = RiskMetricsPeriod(
|
||||
start_session=self.start_session,
|
||||
end_session=self.end_session,
|
||||
returns=self.algo_returns,
|
||||
benchmark_returns=self.benchmark_returns,
|
||||
trading_calendar=self.trading_calendar,
|
||||
treasury_curves=self.env.treasury_curves,
|
||||
)
|
||||
metrics = [
|
||||
"algorithm_period_returns",
|
||||
"benchmark_period_returns",
|
||||
"excess_return",
|
||||
"num_trading_days",
|
||||
"benchmark_volatility",
|
||||
"algorithm_volatility",
|
||||
"sharpe",
|
||||
"sortino",
|
||||
"information",
|
||||
"beta",
|
||||
"alpha",
|
||||
"max_drawdown",
|
||||
"max_leverage",
|
||||
"algorithm_returns",
|
||||
"benchmark_returns",
|
||||
]
|
||||
representation = test_period.__repr__()
|
||||
|
||||
assert all([metric in representation for metric in metrics])
|
||||
|
||||
@@ -873,10 +873,10 @@ def before_trading_start(context, data):
|
||||
|
||||
res2 = algo2.run(self.data_portal)
|
||||
|
||||
# FIXME I think we are getting Nans due to fixed benchmark,
|
||||
# so dropping them for now.
|
||||
res1 = res1.fillna(method='ffill')
|
||||
res2 = res2.fillna(method='ffill')
|
||||
# There are some np.NaN values in the first row because there is not
|
||||
# enough data to calculate the metric, e.g. beta.
|
||||
res1 = res1.fillna(value=0)
|
||||
res2 = res2.fillna(value=0)
|
||||
|
||||
np.testing.assert_array_equal(res1, res2)
|
||||
|
||||
|
||||
@@ -1191,9 +1191,9 @@ class DataPortal(object):
|
||||
|
||||
if data_frequency == "minute":
|
||||
freq_str = "1m"
|
||||
calculated_bar_count = self._get_minute_count_for_transform(
|
||||
calculated_bar_count = int(self._get_minute_count_for_transform(
|
||||
dt, bars
|
||||
)
|
||||
))
|
||||
else:
|
||||
freq_str = "1d"
|
||||
calculated_bar_count = bars
|
||||
|
||||
@@ -27,7 +27,7 @@ from . risk import (
|
||||
choose_treasury
|
||||
)
|
||||
|
||||
from qrisk import (
|
||||
from empyrical import (
|
||||
alpha,
|
||||
annual_volatility,
|
||||
beta,
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
import functools
|
||||
|
||||
import logbook
|
||||
import numpy as np
|
||||
import numpy.linalg as la
|
||||
|
||||
from six import iteritems
|
||||
|
||||
@@ -26,10 +24,11 @@ import pandas as pd
|
||||
from . import risk
|
||||
from . risk import check_entry
|
||||
|
||||
from qrisk import (
|
||||
from empyrical import (
|
||||
alpha,
|
||||
annual_volatility,
|
||||
beta,
|
||||
cum_returns,
|
||||
downside_risk,
|
||||
information_ratio,
|
||||
max_drawdown,
|
||||
@@ -46,7 +45,6 @@ choose_treasury = functools.partial(risk.choose_treasury,
|
||||
class RiskMetricsPeriod(object):
|
||||
def __init__(self, start_session, end_session, returns, trading_calendar,
|
||||
treasury_curves, benchmark_returns, algorithm_leverages=None):
|
||||
|
||||
if treasury_curves.index[-1] >= start_session:
|
||||
mask = ((treasury_curves.index >= start_session) &
|
||||
(treasury_curves.index <= end_session))
|
||||
@@ -79,10 +77,10 @@ class RiskMetricsPeriod(object):
|
||||
|
||||
def calculate_metrics(self):
|
||||
self.benchmark_period_returns = \
|
||||
self.calculate_period_returns(self.benchmark_returns)
|
||||
cum_returns(self.benchmark_returns).iloc[-1]
|
||||
|
||||
self.algorithm_period_returns = \
|
||||
self.calculate_period_returns(self.algorithm_returns)
|
||||
cum_returns(self.algorithm_returns).iloc[-1]
|
||||
|
||||
if not self.algorithm_returns.index.equals(
|
||||
self.benchmark_returns.index
|
||||
@@ -115,7 +113,6 @@ class RiskMetricsPeriod(object):
|
||||
)
|
||||
self.sharpe = sharpe_ratio(
|
||||
self.algorithm_returns,
|
||||
self.benchmark_returns
|
||||
)
|
||||
# The consumer currently expects a 0.0 value for sharpe in period,
|
||||
# this differs from cumulative which was np.nan.
|
||||
@@ -138,9 +135,6 @@ class RiskMetricsPeriod(object):
|
||||
self.algorithm_returns,
|
||||
self.benchmark_returns
|
||||
)
|
||||
self.algorithm_covariance, self.benchmark_variance, \
|
||||
self.condition_number, self.eigen_values \
|
||||
= self.calculate_covariance()
|
||||
self.beta = beta(
|
||||
self.algorithm_returns,
|
||||
self.benchmark_returns
|
||||
@@ -193,16 +187,12 @@ class RiskMetricsPeriod(object):
|
||||
"sharpe",
|
||||
"sortino",
|
||||
"information",
|
||||
"algorithm_covariance",
|
||||
"benchmark_variance",
|
||||
"beta",
|
||||
"alpha",
|
||||
"max_drawdown",
|
||||
"max_leverage",
|
||||
"algorithm_returns",
|
||||
"benchmark_returns",
|
||||
"condition_number",
|
||||
"eigen_values"
|
||||
]
|
||||
|
||||
for metric in metrics:
|
||||
@@ -226,45 +216,6 @@ class RiskMetricsPeriod(object):
|
||||
returns = returns[mask]
|
||||
return returns
|
||||
|
||||
def calculate_period_returns(self, returns):
|
||||
period_returns = (1. + returns).prod() - 1
|
||||
return period_returns
|
||||
|
||||
def calculate_covariance(self):
|
||||
"""
|
||||
|
||||
.. math::
|
||||
|
||||
\\beta_a = \\frac{\mathrm{Cov}(r_a,r_p)}{\mathrm{Var}(r_p)}
|
||||
|
||||
http://en.wikipedia.org/wiki/Beta_(finance)
|
||||
"""
|
||||
# it doesn't make much sense to calculate beta for less than two days,
|
||||
# so return nan.
|
||||
if len(self.algorithm_returns) < 2:
|
||||
return np.nan, np.nan, np.nan, []
|
||||
|
||||
returns_matrix = np.vstack([self.algorithm_returns,
|
||||
self.benchmark_returns])
|
||||
C = np.cov(returns_matrix, ddof=1)
|
||||
|
||||
# If there are missing benchmark values, then we can't calculate the
|
||||
# beta.
|
||||
if not np.isfinite(C).all():
|
||||
return np.nan, np.nan, np.nan, []
|
||||
|
||||
eigen_values = la.eigvals(C)
|
||||
condition_number = max(eigen_values) / min(eigen_values)
|
||||
algorithm_covariance = C[0][1]
|
||||
benchmark_variance = C[1][1]
|
||||
|
||||
return (
|
||||
algorithm_covariance,
|
||||
benchmark_variance,
|
||||
condition_number,
|
||||
eigen_values
|
||||
)
|
||||
|
||||
def calculate_max_leverage(self):
|
||||
if self.algorithm_leverages is None:
|
||||
return 0.0
|
||||
|
||||
Reference in New Issue
Block a user