Skip to content

Commit 80ac020

Browse files
author
Christine Koulopoulos
authored
feat(examples): Adding component manager examples (#62)
1 parent 35f5a04 commit 80ac020

4 files changed

+1005
-0
lines changed
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import time
2+
import os
3+
import uuid
4+
import pandas as pd
5+
6+
from fds.analyticsapi.engines import ApiException
7+
from fds.analyticsapi.engines.api.pa_calculations_api import PACalculationsApi
8+
from fds.analyticsapi.engines.api_client import ApiClient
9+
from fds.analyticsapi.engines.configuration import Configuration
10+
from fds.analyticsapi.engines.model.pa_calculation_parameters_root import PACalculationParametersRoot
11+
from fds.analyticsapi.engines.model.pa_calculation_parameters import PACalculationParameters
12+
from fds.analyticsapi.engines.model.pa_date_parameters import PADateParameters
13+
from fds.analyticsapi.engines.model.pa_identifier import PAIdentifier
14+
from fds.protobuf.stach.extensions.StachVersion import StachVersion
15+
from fds.protobuf.stach.extensions.StachExtensionFactory import StachExtensionFactory
16+
from fds.analyticsapi.engines.api.templated_pa_components_api import TemplatedPAComponentsApi
17+
from fds.analyticsapi.engines.api.linked_pa_templates_api import LinkedPATemplatesApi
18+
from fds.analyticsapi.engines.model.templated_pa_component_parameters import TemplatedPAComponentParameters
19+
from fds.analyticsapi.engines.model.templated_pa_component_parameters_root import TemplatedPAComponentParametersRoot
20+
from fds.analyticsapi.engines.model.pa_component_data import PAComponentData
21+
from fds.analyticsapi.engines.model.pa_date_parameters import PADateParameters
22+
from fds.analyticsapi.engines.model.pa_identifier import PAIdentifier
23+
from fds.analyticsapi.engines.model.pa_calculation_group import PACalculationGroup
24+
from fds.analyticsapi.engines.model.pa_calculation_column import PACalculationColumn
25+
from fds.analyticsapi.engines.model.linked_pa_template_parameters import LinkedPATemplateParameters
26+
from fds.analyticsapi.engines.model.template_content_types import TemplateContentTypes
27+
from fds.analyticsapi.engines.model.linked_pa_template_parameters_root import LinkedPATemplateParametersRoot
28+
from fds.analyticsapi.engines.api.components_api import ComponentsApi
29+
from fds.analyticsapi.engines.model.component_summary import ComponentSummary
30+
from fds.analyticsapi.engines.api.columns_api import ColumnsApi
31+
from fds.analyticsapi.engines.api.column_statistics_api import ColumnStatisticsApi
32+
from fds.analyticsapi.engines.model.column_statistic import ColumnStatistic
33+
from fds.analyticsapi.engines.api.groups_api import GroupsApi
34+
from fds.analyticsapi.engines.model.group import Group
35+
36+
from urllib3 import Retry
37+
38+
host = os.environ['FACTSET_HOST']
39+
fds_username = os.environ['FACTSET_USERNAME']
40+
fds_api_key = os.environ['FACTSET_API_KEY']
41+
proxy_url = os.environ['PROXY_URL']
42+
43+
def main():
44+
config = Configuration()
45+
config.host = host
46+
config.username = fds_username
47+
config.password = fds_api_key
48+
config.discard_unknown_keys = True
49+
# add proxy and/or disable ssl verification according to your development environment
50+
# config.proxy = proxy_url
51+
config.verify_ssl = False
52+
53+
# Setting configuration to retry api calls on http status codes of 429 and 503.
54+
config.retries = Retry(total=3, status=3, status_forcelist=frozenset([429, 503]), backoff_factor=2,
55+
raise_on_status=False)
56+
57+
api_client = ApiClient(configuration=config)
58+
59+
try:
60+
column_name = "Port. Average Weight"
61+
column_category = "Portfolio/Position Data"
62+
column_statistic_name = "Active Weights"
63+
64+
group_category = "JP Morgan CEMBI "
65+
group_name = "Country - JP Morgan CEMBI "
66+
67+
component_document = "PA_DOCUMENTS:DEFAULT"
68+
component_name = "Weights"
69+
component_category = "Weights / Exposures"
70+
71+
linked_pa_template_directory = "Personal:LinkedPATemplates/"
72+
templated_pa_component_directory = "Personal:TemplatedPAComponents/"
73+
74+
portfolio = "BENCH:SP50"
75+
benchmark = "BENCH:R.1000"
76+
startdate = "20180101"
77+
enddate = "20181231"
78+
frequency = "Monthly"
79+
currencyisocode = "USD"
80+
componentdetail = "GROUPS"
81+
directory = "Factset"
82+
83+
# uncomment the below code line to setup cache control; max-stale=0 will be a fresh adhoc run and the max-stale value is in seconds.
84+
# Results are by default cached for 12 hours; Setting max-stale=300 will fetch a cached result which is 5 minutes older.
85+
# cache_control = "max-stale=0"
86+
87+
# get column id
88+
columns_api = ColumnsApi(api_client=api_client)
89+
column = columns_api.get_pa_columns(
90+
name = column_name,
91+
category = column_category,
92+
directory = directory
93+
)
94+
column_id = list(column[0].data.keys())[0]
95+
96+
# get column statistics id
97+
column_statistics_api = ColumnStatisticsApi(api_client=api_client)
98+
get_all_column_statistics = column_statistics_api.get_pa_column_statistics()
99+
column_statistic_id = [id for id in list(
100+
get_all_column_statistics[0].data.keys()) if get_all_column_statistics[0].data[id].name == column_statistic_name][0]
101+
102+
# create columns parameter
103+
columns = [PACalculationColumn(id=column_id, statistics=[column_statistic_id])]
104+
105+
# get group id
106+
groups_api = GroupsApi(api_client=api_client)
107+
groups = groups_api.get_pa_groups()
108+
group_id = [id for id in list(
109+
groups[0].data.keys()) if groups[0].data[id].category == group_category and
110+
groups[0].data[id].directory == directory and
111+
groups[0].data[id].name == group_name][0]
112+
113+
# create groups parameter
114+
groups = [PACalculationGroup(id=group_id)]
115+
116+
# get parent component id
117+
components_api = ComponentsApi(api_client=api_client)
118+
components = components_api.get_pa_components(document=component_document)
119+
parent_component_id = [id for id in list(
120+
components[0].data.keys()) if components[0].data[id].name == component_name and
121+
components[0].data[id].category == component_category][0]
122+
123+
# create a linked PA template
124+
linked_pa_template_parameters = LinkedPATemplateParameters(
125+
directory=linked_pa_template_directory,
126+
parent_component_id=parent_component_id,
127+
description="This is a linked PA template that only returns security level data",
128+
content = TemplateContentTypes(
129+
mandatory = ["accounts", "benchmarks"],
130+
optional = ["groups", "columns","currencyisocode", "componentdetail"],
131+
locked = ["dates"]
132+
)
133+
)
134+
135+
linked_pa_template_parameters_root = LinkedPATemplateParametersRoot(
136+
data = linked_pa_template_parameters
137+
)
138+
139+
linked_pa_template_api = LinkedPATemplatesApi(api_client=api_client)
140+
141+
response = linked_pa_template_api.create_linked_pa_templates(
142+
linked_pa_template_parameters_root = linked_pa_template_parameters_root)
143+
144+
# create a templated component
145+
parent_template_id = response[0].data.get("id")
146+
147+
templated_pa_component_parameters = TemplatedPAComponentParameters(
148+
directory=templated_pa_component_directory,
149+
parent_template_id=parent_template_id,
150+
description="This is a templated PA component",
151+
component_data = PAComponentData(
152+
accounts = [PAIdentifier(id=portfolio)],
153+
benchmarks = [PAIdentifier(id=benchmark)],
154+
columns = columns,
155+
groups = groups,
156+
currencyisocode = currencyisocode,
157+
componentdetail = componentdetail
158+
)
159+
)
160+
161+
templated_pa_component_parameters_root = TemplatedPAComponentParametersRoot(
162+
data = templated_pa_component_parameters
163+
)
164+
165+
templated_pa_components_api = TemplatedPAComponentsApi(api_client=api_client)
166+
167+
response = templated_pa_components_api.create_templated_pa_components(
168+
templated_pa_component_parameters_root = templated_pa_component_parameters_root)
169+
170+
component_id = response[0].data.get("id")
171+
172+
print("PA Component Id: " + component_id)
173+
174+
# do PA calculation with given templated component id
175+
pa_accounts = [PAIdentifier(id=portfolio)]
176+
pa_benchmarks = [PAIdentifier(id=benchmark)]
177+
pa_dates = PADateParameters(
178+
startdate=startdate, enddate=enddate, frequency=frequency)
179+
180+
pa_calculation_parameters = {"1": PACalculationParameters(componentid=component_id, accounts=pa_accounts,
181+
benchmarks=pa_benchmarks, dates=pa_dates),
182+
"2": PACalculationParameters(componentid=component_id, accounts=pa_accounts,
183+
benchmarks=pa_benchmarks, dates=pa_dates)}
184+
185+
pa_calculation_parameter_root = PACalculationParametersRoot(
186+
data=pa_calculation_parameters)
187+
188+
pa_calculations_api = PACalculationsApi(api_client=api_client)
189+
190+
post_and_calculate_response = pa_calculations_api.post_and_calculate(
191+
pa_calculation_parameters_root=pa_calculation_parameter_root)
192+
193+
if post_and_calculate_response[1] == 202 or post_and_calculate_response[1] == 200:
194+
calculation_id = post_and_calculate_response[0].data.calculationid
195+
print("Calculation Id: " + calculation_id)
196+
197+
status_response = pa_calculations_api.get_calculation_status_by_id(id=calculation_id)
198+
199+
while status_response[1] == 202:
200+
max_age = '5'
201+
age_value = status_response[2].get("cache-control")
202+
if age_value is not None:
203+
max_age = age_value.replace("max-age=", "")
204+
print('Sleeping: ' + max_age)
205+
time.sleep(int(max_age))
206+
status_response = pa_calculations_api.get_calculation_status_by_id(calculation_id)
207+
208+
for (calculation_unit_id, calculation_unit) in status_response[0].data.units.items():
209+
if calculation_unit.status == "Success":
210+
print("Calculation Unit Id: " +
211+
calculation_unit_id + " Succeeded!!!")
212+
result_response = pa_calculations_api.get_calculation_unit_result_by_id(id=calculation_id,
213+
unit_id=calculation_unit_id)
214+
output_calculation_result(result=result_response[0]['data'])
215+
else:
216+
print("Calculation Unit Id:" +
217+
calculation_unit_id + " Failed!!!")
218+
print("Error message : " + str(calculation_unit.errors))
219+
else:
220+
print("Calculation creation failed")
221+
print("Error status : " + str(post_and_calculate_response[1]))
222+
print("Error message : " + str(post_and_calculate_response[0]))
223+
224+
except ApiException as e:
225+
print("Api exception Encountered")
226+
print(e)
227+
exit()
228+
229+
230+
def output_calculation_result(result):
231+
print("Calculation Result")
232+
stachBuilder = StachExtensionFactory.get_row_organized_builder(
233+
StachVersion.V2)
234+
stachExtension = stachBuilder.set_package(pkg=result).build()
235+
dataFramesList = stachExtension.convert_to_dataframe()
236+
print(dataFramesList)
237+
# generate_excel(dataFramesList) # Uncomment this line to get the result in table format exported to excel file.
238+
239+
240+
def generate_excel(data_frames_list):
241+
for dataFrame in data_frames_list:
242+
writer = pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
243+
str(uuid.uuid1()) + ".xlsx")
244+
dataFrame.to_excel(excel_writer=writer)
245+
writer.save()
246+
writer.close()
247+
248+
249+
if __name__ == '__main__':
250+
main()

0 commit comments

Comments
 (0)