Style Performance and Risk Analysis (SPAR) Engine API

  • SECTIONS
  • Overview
  • API Definition
  • API Documentation
  • SDK Libraries
  • FactSet Connectors
  • Code Snippet
  • Changelog
Overview

SPAR is a returns-based portfolio analysis application used to analyze the style, performance, and risk of portfolios. It enables users to conduct peer universe and style analysis to compare selected portfolios, benchmarks, and funds against each other.

Features:

  • Style Analysis: Utilizes the methodology developed by William Sharpe to identify and monitor the style of a portfolio.
  • Performance Analysis: Provides performance metrics to evaluate the returns of portfolios against a large universe of equity and fixed income benchmarks.
  • Risk Analysis: Offers over 70 risk and regression statistics such as beta, standard deviation, r-squared, alpha, and tracking error.
  • Peer Group Analysis: Allows users to determine the peer rankings of portfolios and benchmark them against various mutual funds, institutional, and consultant databases.
  • Data Sources: SPAR sources peer universe data from different providers including Lipper, Morningstar, eVestment, Mercer, Investment Metrics, and PSN. Access to these databases is subscription based.

Using an existing SPAR document set up in the FactSet workstation, the API can be used to expose this analytical data. It enables developers to retrieve, update, and manipulate data programmatically, facilitating integration and synchronization between systems. Native connectors such as with Power BI enables developers to extract SPAR data and co-mingle with external sources to create custom dashboards.

By making use of this API, end users can gain valuable insights into their portfolios, make informed investment decisions, and effectively manage risk.

An example flow is given below:

  1. Identify the component ID by using the underlying document as an input to the /components endpoint
  2. Take this component ID and populate it in a POST body and send to the /calculations endpoint
  3. The results will be given back if calculated within the X-FactSet-Api-Long-Running-Deadline header value (in seconds) else you can take the calculation ID and use with the /calculation/{id}/units/{unitID}/result endpoint

Please use the “Report Issue” or “Try For Free” buttons to find out more.

(Please note our Tableau connector has now been retired.)

API Definition
SDK Libraries
Code Snippet
Building and running a single calculation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using FactSet.Protobuf.Stach.Extensions;
using FactSet.SDK.SPAREngine.Api;
using FactSet.SDK.SPAREngine.Client;
using FactSet.SDK.SPAREngine.Model;
using FactSet.SDK.Utils.Authentication;

namespace FactSet.AnalyticsAPI.SPARESDK.Example
{
    public class SPAREngineSingleUnitExample
    {
        private static readonly string BasePath = Environment.GetEnvironmentVariable("FACTSET_HOST");
        private static readonly string UserName = Environment.GetEnvironmentVariable("FACTSET_USERNAME");
        private static readonly string Password = Environment.GetEnvironmentVariable("FACTSET_PASSWORD");
        private const string SPARDefaultDocument = "pmw_root:/spar_documents/Factset Default Document";
        private const string SPARComponentName = "Returns Table";
        private const string SPARComponentCategory = "Raw Data / Returns";
        private const string SPARBenchmark1 = "R.1000";
        private const string SPARBenchmark2 = "RUSSELL_P:R.2000";
        private const string SPARBenchmarkPrefix = "RUSSELL";
        private const string SPARBenchmarkReturnType = "GTR";
        private const string SPARCurrency = "USD";
        private const string SPARStartDate = "20180101";
        private const string SPAREndDate = "20181231";
        private const string SPARFrequency = "Monthly";
        private static SDK.SPAREngine.Client.Configuration _engineApiConfiguration;

        public static async Task Main(string[] args)
        {
            try
            {
                var sparCalculationParameters = await GetSparCalculationParametersAsync();

                var calculationParameters = new SPARCalculationParametersRoot
                {
                    Data = new Dictionary<string, SPARCalculationParameters> { { "1", sparCalculationParameters } }
                };

                var calculationApi = new SPARCalculationsApi(await GetApiConfigurationAsync());

                var calculationResponse = calculationApi.PostAndCalculateWithHttpInfo(null, null, calculationParameters);
                //Comment the above line and uncomment the below lines to add cache control configuration. Results are by default cached for 12 hours; Setting max-stale=300 will fetch a cached result which is at max 5 minutes older.
                //var cacheControl = "max-stale=0";
                //var calculationResponse = calculationApi.PostAndCalculateWithHttpInfo(null, cacheControl, calculationParameters);

                if (calculationResponse.StatusCode == HttpStatusCode.Created)
                {
                    ObjectRoot result = (ObjectRoot)calculationResponse.Data.Response;
                    PrintResult(result);
                    return;
                }

                CalculationStatusRoot status = (CalculationStatusRoot)calculationResponse.Data.Response;
                var calculationId = status.Data.Calculationid;
                Console.WriteLine("Calculation Id: " + calculationId);
                ApiResponse<CalculationStatusRoot> getStatusResponse = null;

                while (status.Data.Status == CalculationStatus.StatusEnum.Queued || status.Data.Status == CalculationStatus.StatusEnum.Executing)
                {
                    if (getStatusResponse != null)
                    {
                        if (getStatusResponse.Headers.ContainsKey("Cache-Control"))
                        {
                            var maxAge = getStatusResponse.Headers["Cache-Control"][0];
                            if (string.IsNullOrWhiteSpace(maxAge))
                            {
                                Console.WriteLine("Sleeping for 2 seconds");
                                // Sleep for at least 2 seconds.
                                Thread.Sleep(2000);
                            }
                            else
                            {
                                var age = int.Parse(maxAge.Replace("max-age=", ""));
                                Console.WriteLine($"Sleeping for {age} seconds");
                                Thread.Sleep(age * 1000);
                            }
                        }
                    }

                    getStatusResponse = calculationApi.GetCalculationStatusByIdWithHttpInfo(calculationId);
                    status = getStatusResponse.Data;
                }
                Console.WriteLine("Calculation Completed");


                foreach (var sparCalculation in status.Data.Units)
                {
                    if (sparCalculation.Value.Status == CalculationUnitStatus.StatusEnum.Success)
                    {
                        var resultResponse = calculationApi.GetCalculationUnitResultByIdWithHttpInfo(calculationId, sparCalculation.Key);
                        PrintResult(resultResponse.Data);
                    }
                    else
                    {
                        Console.WriteLine($"Calculation Unit Id : {sparCalculation.Key} Failed!!!");
                        Console.WriteLine($"Error message : {sparCalculation.Value.Errors}");
                    }
                }

                Console.ReadKey();
            }
            catch (ApiException e)
            {
                Console.WriteLine("Exception when calling SPARCalculationsApi : " + e.Message);
                Console.WriteLine($"Status Code: {e.ErrorCode}");
                Console.WriteLine(e.StackTrace);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        private static async Task<SDK.SPAREngine.Client.Configuration> GetApiConfigurationAsync()
        {
            //Supported authentication methods are below,
            //choose one that satisfies your use case.

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            if (_engineApiConfiguration != null)
            {
                return _engineApiConfiguration;
            }

            #region BasicAuthentication
            
            /* Basic authentication: FactSetApiKey */
            // See https://github.com/FactSet/enterprise-sdk#api-key
            // for information how to create an API key
            _engineApiConfiguration = new SDK.SPAREngine.Client.Configuration
            {
                BasePath = BasePath,
                Username = UserName,
                Password = Password,
            };
            #endregion

            //Uncomment below lines for adding the proxy configuration
            //System.Net.WebProxy webProxy = new System.Net.WebProxy("http://myProxyUrl:80/");
            //webProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
            //_engineApiConfiguration.Proxy = webProxy;

            #region FactSetOAuth2
            /* (Preferred) OAuth 2.0: FactSetOAuth2 */
            // See https://github.com/FactSet/enterprise-sdk#oauth-20
            // for information on how to create the app-config.json file
            // See https://github.com/FactSet/enterprise-sdk-utils-dotnet#authentication
            // for more information on using the ConfidentialClient class

            //Uncomment below lines and comment the above lines(region:BasicAuthentication) for FactSetOAuth2 Authentication
            //ConfidentialClient confidentialClient = await ConfidentialClient.CreateAsync("");
            //_engineApiConfiguration = new FactSet.SDK.SPAREngine.Client.Configuration();
            //_engineApiConfiguration.OAuth2Client = confidentialClient; 
            #endregion

            return _engineApiConfiguration;
        }

        private static async Task<SPARCalculationParameters> GetSparCalculationParametersAsync()
        {
            var componentsApi = new ComponentsApi(await GetApiConfigurationAsync());

            var componentsResponse = componentsApi.GetSPARComponents(SPARDefaultDocument);

            var sparComponentId = componentsResponse.Data.FirstOrDefault(component => (component.Value.Name == SPARComponentName && component.Value.Category == SPARComponentCategory)).Key;
            Console.WriteLine($"SPAR Component Id : {sparComponentId}");

            var sparAccountIdentifier = new SPARIdentifier(SPARBenchmark1, SPARBenchmarkReturnType, SPARBenchmarkPrefix);
            var sparAccounts = new List<SPARIdentifier> { sparAccountIdentifier };
            var sparBenchmarkIdentifier = new SPARIdentifier(SPARBenchmark2, SPARBenchmarkReturnType, SPARBenchmarkPrefix);
            var sparDates = new SPARDateParameters(SPARStartDate, SPAREndDate, SPARFrequency);

            var sparCalculation = new SPARCalculationParameters(sparComponentId, sparAccounts, sparBenchmarkIdentifier, sparDates, SPARCurrency);

            return sparCalculation;
        }

        private static void PrintResult(ObjectRoot result)
        {
            Console.WriteLine("Calculation Result");

            // converting the data to Package object
            var stachBuilder = StachExtensionFactory.GetRowOrganizedBuilder();
            var stachExtension = stachBuilder.SetPackage(result.Data).Build();
            // To convert package to 2D tables.
            var tables = stachExtension.ConvertToTable();

            Console.WriteLine(tables[0]);
        }

    }
}
Building and running multiple calculations
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using FactSet.Protobuf.Stach.Extensions;
using FactSet.SDK.SPAREngine.Api;
using FactSet.SDK.SPAREngine.Client;
using FactSet.SDK.SPAREngine.Model;
using FactSet.SDK.Utils.Authentication;

namespace FactSet.AnalyticsAPI.SPARESDK.Example
{
    public class SPAREngineMultipleUnitExample
    {
        private static readonly string BasePath = Environment.GetEnvironmentVariable("FACTSET_HOST");
        private static readonly string UserName = Environment.GetEnvironmentVariable("FACTSET_USERNAME");
        private static readonly string Password = Environment.GetEnvironmentVariable("FACTSET_PASSWORD");
        private const string SPARDefaultDocument = "pmw_root:/spar_documents/Factset Default Document";
        private const string SPARComponentName = "Returns Table";
        private const string SPARComponentCategory = "Raw Data / Returns";
        private const string SPARBenchmark1 = "R.1000";
        private const string SPARBenchmark2 = "RUSSELL_P:R.2000";
        private const string SPARBenchmarkPrefix = "RUSSELL";
        private const string SPARBenchmarkReturnType = "GTR";
        private const string SPARCurrency = "USD";
        private const string SPARStartDate = "20180101";
        private const string SPAREndDate = "20181231";
        private const string SPARFrequency = "Monthly";
        private static SDK.SPAREngine.Client.Configuration _engineApiConfiguration;

        public static async Task Main(string[] args)
        {
            try
            {
                var sparCalculationParameters = await GetSparCalculationParametersAsync();

                var calculationParameters = new SPARCalculationParametersRoot
                {
                    Data = new Dictionary<string, SPARCalculationParameters> { { "1", sparCalculationParameters }, { "2", sparCalculationParameters } }
                };

                var calculationApi = new SPARCalculationsApi(await GetApiConfigurationAsync());

                var calculationResponse = calculationApi.PostAndCalculateWithHttpInfo(null, null, calculationParameters);
                //Comment the above line and uncomment the below lines to add cache control configuration. Results are by default cached for 12 hours; Setting max-stale=300 will fetch a cached result which is at max 5 minutes older.
                //var cacheControl = "max-stale=0";
                //var calculationResponse = calculationApi.PostAndCalculateWithHttpInfo(null, cacheControl, calculationParameters);

                if (calculationResponse.StatusCode == HttpStatusCode.Created)
                {
                    ObjectRoot result = (ObjectRoot)calculationResponse.Data.Response;
                    PrintResult(result);
                    return;
                }

                CalculationStatusRoot status = (CalculationStatusRoot)calculationResponse.Data.Response;
                var calculationId = status.Data.Calculationid;
                Console.WriteLine("Calculation Id: " + calculationId);
                ApiResponse<CalculationStatusRoot> getStatusResponse = null;

                while (status.Data.Status == CalculationStatus.StatusEnum.Queued || status.Data.Status == CalculationStatus.StatusEnum.Executing)
                {
                    if (getStatusResponse != null)
                    {
                        if (getStatusResponse.Headers.ContainsKey("Cache-Control"))
                        {
                            var maxAge = getStatusResponse.Headers["Cache-Control"][0];
                            if (string.IsNullOrWhiteSpace(maxAge))
                            {
                                Console.WriteLine("Sleeping for 2 seconds");
                                // Sleep for at least 2 seconds.
                                Thread.Sleep(2000);
                            }
                            else
                            {
                                var age = int.Parse(maxAge.Replace("max-age=", ""));
                                Console.WriteLine($"Sleeping for {age} seconds");
                                Thread.Sleep(age * 1000);
                            }
                        }
                    }

                    getStatusResponse = calculationApi.GetCalculationStatusByIdWithHttpInfo(calculationId);
                    status = getStatusResponse.Data;
                }
                Console.WriteLine("Calculation Completed");


                foreach (var sparCalculation in status.Data.Units)
                {
                    if (sparCalculation.Value.Status == CalculationUnitStatus.StatusEnum.Success)
                    {
                        var resultResponse = calculationApi.GetCalculationUnitResultByIdWithHttpInfo(calculationId, sparCalculation.Key);
                        PrintResult(resultResponse.Data);
                    }
                    else
                    {
                        Console.WriteLine($"Calculation Unit Id : {sparCalculation.Key} Failed!!!");
                        Console.WriteLine($"CalculationId:UnitId : {sparCalculation.Value.Errors?.FirstOrDefault()?.Id}");
                        Console.WriteLine($"Error message : {sparCalculation.Value.Errors?.FirstOrDefault()?.Detail}");
                    }
                }

                Console.ReadKey();
            }
            catch (ApiException e)
            {
                Console.WriteLine("Exception when calling SPARCalculationsApi : " + e.Message);
                Console.WriteLine($"Status Code: {e.ErrorCode}");
                Console.WriteLine(e.StackTrace);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        private static async Task<SDK.SPAREngine.Client.Configuration> GetApiConfigurationAsync()
        {
            //Supported authentication methods are below,
            //choose one that satisfies your use case.

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            if (_engineApiConfiguration != null)
            {
                return _engineApiConfiguration;
            }

            #region BasicAuthentication
            /* Basic authentication: FactSetApiKey */
            // See https://github.com/FactSet/enterprise-sdk#api-key
            // for information how to create an API key
            _engineApiConfiguration = new SDK.SPAREngine.Client.Configuration
            {
                BasePath = BasePath,
                Username = UserName,
                Password = Password,
            };
            #endregion

            //Uncomment below lines for adding the proxy configuration
            //System.Net.WebProxy webProxy = new System.Net.WebProxy("http://myProxyUrl:80/");
            //webProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
            //_engineApiConfiguration.Proxy = webProxy;

            #region FactSetOAuth2
            /* (Preferred) OAuth 2.0: FactSetOAuth2 */
            // See https://github.com/FactSet/enterprise-sdk#oauth-20
            // for information on how to create the app-config.json file
            // See https://github.com/FactSet/enterprise-sdk-utils-dotnet#authentication
            // for more information on using the ConfidentialClient class

            //Uncomment below lines and comment the above lines(region:BasicAuthentication) for FactSetOAuth2 Authentication
            //ConfidentialClient confidentialClient = await ConfidentialClient.CreateAsync("");
            //_engineApiConfiguration = new FactSet.SDK.SPAREngine.Client.Configuration();
            //_engineApiConfiguration.OAuth2Client = confidentialClient; 
            #endregion

            return _engineApiConfiguration;
        }

        private static async Task<SPARCalculationParameters> GetSparCalculationParametersAsync()
        {
            var componentsApi = new ComponentsApi(await GetApiConfigurationAsync());

            var componentsResponse = componentsApi.GetSPARComponents(SPARDefaultDocument);

            var sparComponentId = componentsResponse.Data.FirstOrDefault(component => (component.Value.Name == SPARComponentName && component.Value.Category == SPARComponentCategory)).Key;
            Console.WriteLine($"SPAR Component Id : {sparComponentId}");

            var sparAccountIdentifier = new SPARIdentifier(SPARBenchmark1, SPARBenchmarkReturnType, SPARBenchmarkPrefix);
            var sparAccounts = new List<SPARIdentifier> { sparAccountIdentifier };
            var sparBenchmarkIdentifier = new SPARIdentifier(SPARBenchmark2, SPARBenchmarkReturnType, SPARBenchmarkPrefix);
            var sparDates = new SPARDateParameters(SPARStartDate, SPAREndDate, SPARFrequency);

            var sparCalculation = new SPARCalculationParameters(sparComponentId, sparAccounts, sparBenchmarkIdentifier, sparDates, SPARCurrency);

            return sparCalculation;
        }

        private static void PrintResult(ObjectRoot result)
        {
            Console.WriteLine("Calculation Result");

            // converting the data to Package object
            var stachBuilder = StachExtensionFactory.GetRowOrganizedBuilder();
            var stachExtension = stachBuilder.SetPackage(result.Data).Build();
            // To convert package to 2D tables.
            var tables = stachExtension.ConvertToTable();

            Console.WriteLine(tables[0]);
        }

    }
}
Changelog

Version 3

Summary

  • Version 3.14.0 - Released on 11/11/2024
  • Version 3.13.9 - Released on 05/27/2024
  • Version 3.13.8 - Released on 03/25/2024
  • Version 3.13.7 - Released on 12/18/2023
  • Version 3.13.6 - Released on 10/25/2023
  • Version 3.13.5 - Released on 09/25/2023
  • Version 3.13.4 - Released on 08/21/2023
  • Version 3.13.3 - Released on 07/24/2023
  • Version 3.13.2 - Released on 06/23/2023
  • Version 3.13.1 - Released on 05/23/2023
  • Version 3.13.0 - Released on 04/25/2023
  • Version 3.12.0 - Released on 01/23/2023
  • Version 3.11.0 - Released on 06/06/2022
  • Version 3.10.0 - Released on 04/18/2022
  • Version 3.9.1 - Released on 02/14/2022
  • Version 3.9.0 - Released on 11/22/2021
  • Version 3.8.0 - Released on 10/21/2021
  • Version 3.7.0 - Released on 09/20/2021
  • Version 3.6.0 - Released on 09/07/2021
  • Version 3.6.0 - Released on 08/23/2021
  • Version 3.5.0 - Released on 08/06/2021
  • Version 3.4.2 - Released on 07/28/2021
  • Version 3.4.1 - Released on 07/19/2021
  • Version 3.3.2 - Released on 07/12/2021
  • Version 3.3.1 - Released on 06/28/2021
  • Version 3.3.0 - Released on 06/07/2021
  • Version 3.2.0 - Released on 05/21/2021
  • Version 3.1.2 - Released on 04/21/2021
  • Version 3.1.1 - Released on 03/20/2021
  • Version 3.1.0 - Released on 03/18/2021
  • Version 3.0.0 - Released on 02/10/2021

Functionality Additions

  • Added support for Inception date calculation with Multiple Portfolios. [v3.14.0]
  • Added new Get SPAR component by ID endpoint. [v3.13.0]
  • Added new Security Response headers [v3.12.0]
  • Added new Get All Calculations endpoint. [v3.11.0]
  • Calculation points are returned in GET status endpoints when a calculation completes successfully. [v3.9.0]
  • New cache-control headers “Age” and “Last-Modified” [v3.6.0]
  • New returns-type lookups endpoint to fetch a SPAR account's returns type [v3.6.0]
  • Support for currency in SPAR calculations [v3.4.1]
  • Deprecated "ContentOrganization" and "ContentType" in favor of added "StachContentOrganization" and "CalculationFormat" [v3.3.1]
  • Support cache-control headers max-age, max-stale, max-stale & max-age [v3.1.0]
  • Initial Release [v3.0.0]

Changes

  • Title and Name in the Overview section have been renamed to Style Performance and Risk Analysis (SPAR) Engine API
  • New "data" top-level object in request and response body
  • New (optional) "meta" top-level object in request and response body
  • STACH v2 returned in results
  • Cache control functionality
  • GET analytics/engines/{engine}/v3/calculations/{id} - now returns calculation parameters instead of calculation status
  • Updated lookup endpoint URLs

Bug Fixes

  • Fixed Duplicate Column Descriptions in API response, improvised error messages for bathc calcautions and minor bug fixes. [v3.13.9]
  • Minor bug fixes. [v3.13.8]
  • Added example value for long-running request header. [v3.13.7]
  • Fixed the schema documentation of the getAllCalculation endpoint. [v3.13.6]
  • Minor bug fixes. [v3.13.5]
  • Fixed error responses in delete endpoint for 404s. [v3.13.4]
  • Removed mandatory field requirement for pageNumber in GET All Calculations endpoint. [v3.13.4]
  • Fixed response headers in case of 429s. [v3.13.3]
  • Fixed float value issue for AnnualizationDays. [v3.13.2]
  • Modified the Cache-control value to 'no store'for the GetSparComponentById endpoint. [v3.13.1]
  • Minor bug fixes [v3.10.0]
  • Fixed an issue where progress percentage on calculation units was not included in POST or GET requests on Engines API [v3.8.0 ]
  • Improved error messaging for Invalid component id [v3.6.0]
  • Minor bug fixes for a multi-unit calculation [v3.5.0]
  • Minor bug fixes [v3.4.1]
  • Fix for the decoding of v3 Document’s endpoint. [v3.3.2]
  • Fix to support row and column STACH content organizations [v3.3.2]
  • Minor fixes for the SimplifiedRow STACH v2 format v[3.0.0]

v2

Summary

  • v2.6.0 - Released on 12/15/20
  • v2.5.6 - Released on 11/16/20
  • v2.5.5 - Released on 10/29/20
  • v2.5.4 - Released on 08/27/20
  • v2.5.3 - Released on 07/23/20
  • v2.5.2 - Released on 06/25/20
  • v2.5.1 - Released on 04/19/20
  • v2.5.0 - Released on 03/26/20
  • v2.4.1 - Released on 02/27/20
  • v2.4.0 - Released on 01/16/20
  • v2.3.0 - Released on 12/12/19
  • v2.2.0 - Released on 11/25/19
  • v2.1.0 - Released on 09/26/19
  • v2.0.0 - Released on 08/15/19

Functionality Additions

  • STACH v2.0 [v2.6.0]
  • Better logging [v2.5.1]
  • Performance improvements [v2.5.0]
  • Performance improvements [v2.4.1]
  • Added endpoint to return the details of a given SPAR benchmark identifier [v2.4.0]
  • Renamed points to units and removed 25-unit limit per request. Points for billing will be handled asynchronously in the backend [v2.3.0]
  • Added error message when a calculation unit fails due to invalid parameters [v2.2.0]
  • Performance improvement [v2.2.0]
  • Added calculation metadata to the result pickup endpoint. The properties include settings used in ‘Run Multiple Calculations’ endpoint and account/benchmark defaults [v2.1.0]
  • Initial release [v2.0.0]

Changes

  • Renamed ‘pointscount’ property to ‘points’ in ‘Get All Active Calculations’ endpoint. Points count related response headers were also updated accordingly in ‘Run Multiple Calculations’ endpoint [v2.1.0]

Bug Fixes

  • Efficient handling of streaming results [v2.6.0]
  • Return 503 on Rate limit transient errors [v2.6.0]
  • Fixing points logging for interactive endpoints [v2.5.6]
  • Sandbox: Returning Created (201) instead of Success (200) for interactive Post [v2.5.5]
  • Fixed bug to respect custom column headers defined in the document [v2.5.5]
  • Fix bug in rate limiting [v2.5.4]
  • Considering the value of the "Include benchmark as portfolio" option on the document settings [v2.5.2]
  • Cache control header fix [v2.5.2]
  • Rate limiting header fix [v2.5.2]
  • Minor bug fixes [v2.5.1]
  • Reverted returning error messages to users as the feature will be handled in a later release [v2.3.0]
  • Improved error handling for invalid requests [v2.2.0]
  • Consistent Component ID's irrespective of document path formatting and casing [v2.2.0]

v1 (Retired)

Summary

  • v1.1.0 - Released on 07/25/19
  • v1.0.0 - Released on 06/13/19

Functionality Additions

  • Added format parameter to Get Result Endpoint to switch between different output formats [v1.1.0]
  • Added ability to create, fetch, and delete multiple SPAR Engine calculations [v1.0.0]
  • Initial release [v1.0.0]

Changes

  • No changes

Bug Fixes

  • No bug fixes