|
| 1 | +import json |
| 2 | +import sys |
| 3 | +import time |
| 4 | +import pandas as pd |
| 5 | +import uuid |
| 6 | +import os |
| 7 | + |
| 8 | +from fds.analyticsapi.engines import ComponentSummary |
| 9 | +from fds.analyticsapi.engines.api.fi_calculations_api import FICalculationsApi |
| 10 | +from fds.analyticsapi.engines.api_client import ApiClient |
| 11 | +from fds.analyticsapi.engines.configuration import Configuration |
| 12 | +from fds.analyticsapi.engines.models.fi_calculation_parameters import FICalculationParameters |
| 13 | +from fds.analyticsapi.engines.models.security import Security |
| 14 | +from fds.analyticsapi.engines.models.job_settings import JobSettings |
| 15 | +from fds.analyticsapi.engines.stach_extensions import StachExtensions |
| 16 | +from fds.protobuf.stach.Package_pb2 import Package |
| 17 | + |
| 18 | +from google.protobuf import json_format |
| 19 | +from google.protobuf.json_format import MessageToJson |
| 20 | +from google.protobuf.json_format import MessageToDict |
| 21 | +from urllib3 import Retry |
| 22 | + |
| 23 | +host = "https://api.factset.com" |
| 24 | +username = os.environ["ANALYTICS_API_USERNAME_SERIAL"] |
| 25 | +password = os.environ["ANALYTICS_API_PASSWORD"] |
| 26 | + |
| 27 | +def main(): |
| 28 | + config = Configuration() |
| 29 | + config.host = host |
| 30 | + config.username = username |
| 31 | + config.password = password |
| 32 | + # add proxy and/or disable ssl verification according to your development environment |
| 33 | + # config.proxy = "<proxyUrl>" |
| 34 | + config.verify_ssl = False |
| 35 | + |
| 36 | + # Setting configuration to retry api calls on http status codes of 429 and 503. |
| 37 | + config.retries = Retry(total=3, status=3, status_forcelist=frozenset([429, 503]), backoff_factor=2, |
| 38 | + raise_on_status=False) |
| 39 | + |
| 40 | + api_client = ApiClient(config) |
| 41 | + |
| 42 | + calculations = ["Security Type", |
| 43 | + "Security Name", |
| 44 | + "Run Status", |
| 45 | + "Elapse Time (seconds)", |
| 46 | + "Calc From Method", |
| 47 | + "Option Pricing Model", |
| 48 | + "Yield Curve Date", |
| 49 | + "Settlement Date", |
| 50 | + "Discount Curve", |
| 51 | + "Price", |
| 52 | + "Yield to No Call", |
| 53 | + "OAS", |
| 54 | + "Effective Duration", |
| 55 | + "Effective Convexity"] |
| 56 | + |
| 57 | + security1 = Security("Price", 100.285, 10000.0, "912828ZG8", "20201202", "UST") |
| 58 | + security2 = Security("Price", 101.138, 200000.0, "US037833AR12", "20201203", "UST") |
| 59 | + |
| 60 | + securities = [security1, security2] |
| 61 | + |
| 62 | + jobSettings = JobSettings("20201201") |
| 63 | + |
| 64 | + fi_calculation_parameters = FICalculationParameters(securities, calculations, jobSettings) |
| 65 | + |
| 66 | + print(fi_calculation_parameters) |
| 67 | + |
| 68 | + fi_calculations_api = FICalculationsApi(api_client) |
| 69 | + run_calculation_response = fi_calculations_api.run_fi_calculation_with_http_info(fi_calculation_parameters = fi_calculation_parameters) |
| 70 | + |
| 71 | + if run_calculation_response[1] != 202 and run_calculation_response[1] != 201: |
| 72 | + print_error(run_calculation_response) |
| 73 | + sys.exit() |
| 74 | + |
| 75 | + if run_calculation_response[1] == 201: |
| 76 | + print_result(run_calculation_response[0]) |
| 77 | + sys.exit() |
| 78 | + |
| 79 | + calculation_id = run_calculation_response[2].get("location").split("/")[-1] |
| 80 | + print("Calculation Id: " + calculation_id) |
| 81 | + |
| 82 | + status_response = fi_calculations_api.get_fi_calculation_by_id_with_http_info(calculation_id) |
| 83 | + while status_response[1] == 202: |
| 84 | + max_age = '5' |
| 85 | + age_value = status_response[2].get("cache-control") |
| 86 | + if age_value is not None: |
| 87 | + max_age = age_value.replace("max-age=", "") |
| 88 | + print('Sleeping: ' + max_age) |
| 89 | + time.sleep(int(max_age)) |
| 90 | + status_response = fi_calculations_api.get_fi_calculation_by_id_with_http_info(calculation_id) |
| 91 | + |
| 92 | + if status_response[1] != 200: |
| 93 | + print_error(status_response) |
| 94 | + sys.exit() |
| 95 | + |
| 96 | + print_result(status_response[0]) |
| 97 | + |
| 98 | + |
| 99 | +def print_result(response): |
| 100 | + # converting the data to Package object |
| 101 | + result = json_format.Parse(json.dumps(response), Package()) |
| 102 | + # print(MessageToJson(result)) # To print the result object as a JSON |
| 103 | + # print(MessageToDict(result)) # To print the result object as a Dictionary |
| 104 | + tables = StachExtensions.convert_to_table_format(result) # To convert result to 2D tables. |
| 105 | + print(tables[0]) # Prints the result in 2D table format. |
| 106 | + # generate_excel(result) # Uncomment this line to get the result in table format exported to excel file. |
| 107 | + |
| 108 | + |
| 109 | +def generate_excel(package): |
| 110 | + for table in StachExtensions.convert_to_table_format(package): |
| 111 | + writer = pd.ExcelWriter(str(uuid.uuid1()) + ".xlsx") |
| 112 | + table.to_excel(excel_writer=writer) |
| 113 | + writer.save() |
| 114 | + writer.close() |
| 115 | + |
| 116 | + |
| 117 | +def print_error(response): |
| 118 | + print("Calculation Failed!!!") |
| 119 | + print("Status Code: " + str(response[1])) |
| 120 | + print("Request Key: " + response[2].get("x-datadirect-request-key")) |
| 121 | + print(response[0]) |
| 122 | + |
| 123 | + |
| 124 | +if __name__ == '__main__': |
| 125 | + main() |
0 commit comments