-
Notifications
You must be signed in to change notification settings - Fork 1
/
fund.py
97 lines (70 loc) · 2.86 KB
/
fund.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import logging
log = logging.getLogger(__name__)
from pandas.tseries.index import bdate_range
from pricing import price_holding
from simple_files import ObjectHolder
__author__ = 'Andy Fundinger - Andy.Fundinger@riskfocus.com'
class Fund(object):
def __init__(self, name, components):
"""Hold information about the composition of a fund.
:type components: pandas.core.frame.DataFrame
"""
super(Fund, self).__init__()
self.name = name
self.components = components
def __getattr__(self, item):
"""Redirect any unknown attribute access to the components panda, this constitutes a proxy
:type item: str
"""
if item[0] != '_':
return getattr(self.components, item)
else:
# Default behaviour
raise AttributeError
def __getitem__(self, key):
"""Redirect any unknown index to the components panda
:param key:
:return:
"""
return self.components[key]
def __len__(self):
"""Fund length is the number of included positions
:return:
"""
return len(self.components)
@property
def start_date(self):
"""Funds start on the date of the first position in the fund.
:return:
"""
return self['start_date'].min()
def price(self, market, model, cob_date):
"""Price the fund by pricing all of its positions
:type market: holders.BaseHolder
:type model: holders.BaseHolder
:type cob_date: str or date
:return:
"""
try:
return self.components.apply(price_holding, 1, args=(market, model, cob_date)).sum()
except KeyError:
log.warning("Fund %s unable to price on %s", self.name, cob_date)
return None
def price_for_dates(self, market, model, dates):
return dates.apply(lambda dt: self.price(market, model, dt.date()))
def hVar(self, market, model, cob_date, days=262):
"""Calculate the historical var for this fund on the given date.
:type market: holders.BaseHolder market data
:type model: simple_files.FileHolder model data for use by pricers
:type cob_date: str cob date to calculate var for
:type days: int number of business days to look back for the historical market data, defaults to 262 which works
by pandas logic
:return:
"""
dates = bdate_range(end=cob_date, periods=days).to_series()
log.info("Calculating hVar using date range [%s:%s]", dates[0].date(), dates[-1].date())
prices = self.price_for_dates(market, model, dates)
return self.price(market, model, cob_date) - prices.dropna().quantile(.05)
class FundsHolder(ObjectHolder):
"A holder that constructs fund objects out of the data stored in this collection"
klass = Fund