The API Wrapper - p123api
Describes the p123api package with objects and functions that facilitate using the P123 API
Introduction
To facilitate using the our Rest API we created a python package that wraps the API endpoints. The package is called p123api
and it makes it very easy to start using the API. It handles several things like retries, authentication and low level http request.
The wrapper is an open source project and is hosted at pypi.org. The package is still being developed, so let us know of any issues or inconsistencies.
For an example using the
p123api
in a Google Colab notebook see this article.
To use p123api
you can start your code like this:
# Install p123api if missing
!pip install --upgrade p123api
import p123api
try:
client = p123api.Client(api_id='YOUR_API_ID', api_key='YOUR_API_KEY_XXXX')
# call package function(s)
res1 = client.p123api_function1()
... etc ...
except p123api.ClientException as e:
print(e)
Functions
Each API endpoint has been wrapped with a function. They are listed below grouped the same way as the API reference. The parameters for the functions should be identical to the API specification. Lastly, for optional parameter the default value when not specified is the first value in the list (if any).
List of functions
(see below for details)
AI Functions | |
---|---|
aifactor_predict | Returns the predictions for a trained predictor. |
Data Functions | |
data | This operation allows you to retrieve large sets of data from our point in time engine. |
data_universe | This operation allows you to retrieve point in time data for a selected universe. |
Universe Functions | |
universe_update | This operation updates the Universe used by API. |
Rank Functions | |
rank_ranks | This operation allows you to retrieve rank data from a ranking system for a specific universe. |
rank_perf | This operation lets you run bucket performance tests of multifactor ranking systems. |
rank_update | This operation updates the "API ranking system" called ApiRankingSystem. |
Screen Functions | |
screen_run | This operation allows you to run a screen. |
screen_backtest | This operation allows you to run a performance backtest of a Screen. |
screen_rolling_backtest | This operation allows you to run and collect the output of rolling screens. |
Strategy Functions | |
strategy | This operation returns the data from the Summary, Current Holdings and Statistics tabs of a strategies or books. |
Data Series Functions | |
data_series_create_update | Create or update a data series. |
data_series_delete | Deletes a data series and the data associated with it. |
data_series_upload | Upload the series data. |
Stock Factors Functions | |
stock_factor_create_update | Create or update a new stock factor. |
stock_factor_delete | Delete a stock factor. |
stock_factor_upload | Upload data from a csv file into an existing stock factor. |
AI Function
aifactor_predict()
Wrapper for POST /aiFactor/predict/{id}
This operation allows you to get the predictions for a trained Predictor. Although you can specify any universe we recommended that you use the same one used to train the predictor.
p123api.Client().aifactor_predict(
id # predictor id
#
# optional
#
,{
"asOfDt": "2024-10-07", # defaults to latest available
"precision": 2,
"universe": "univ name", # defaults to AI Factor universe
"includeNames": False,
"includeFeatures": False,
"figi": 'Share Class' |'Country Composite'
},
to_pandas=True
)
Data Functions
data()
Wrapper for POST /data
This operation allows you to retrieve large sets of data from our point in time engine. You will need to obtain your own license from the data vendor (Factset or Compustat) to fully access. You can try it without a license with the following stocks: IBM, MSFT & INTC and for 5 years of history. Alternatively see the data_universe() operation below to download normalized data.
p123api.Client().data({
# Specify either: tickers, cusips, p123Uids, ciks,
# or gvkeys (Compustat only)
'tickers': ['ticker1', 'ticker2'' ...],
'formulas': ['form1', 'form2', ... ],
'startDt': 'yyyy-mm-dd',
'endDt': 'yyyy-mm-dd',
# optional parameters
'currency': 'USD' | 'CAD' | 'CHF' | 'EUR' | 'GBP' | 'NOK' | 'PLN' | 'SEK' | 'TRY',
'precision': 2 | 3 | 4,
'frequency': 'Every Week' | 'Every N Weeks' (2,3,4,6,8,13,26,52),
'pitMethod': 'Prelim' | 'Complete',
'includeNames': True | False,
'region': 'United States' | 'Canada' | 'North America' | 'Europe' | 'North Atlantic',
'ignoreErrors': True | False #True will ignore invalid tickers, CUSIPs, etc
},True) # True - output to Pandas DataFrame | [False] to JSON.
data_universe()
Wrapper for POST /data/universe
Example Google Colab
This operation allows you to retrieve point in time data for a selected universe. If a preprocessor that normalizes the data is not used, a data license with our vendor might be required. For the universe parameter, specify the name of your custom universe or one of the Portfolio123 universes.
p123api.Client().data_universe({
# Specify the universe name (ex 'SP500'). To use the
# API universe that can be updated with other
# API functions use 'APIUniverse'
"universe": "DJIA" # universe symbol or name
, "asOfDts": ["2024-03-16","2024-03-09"] # use weekend dates
, "formulas": [ "Close(0)/close(5)", "PEExclXorTTM", "SalesGr%TTM" ]
# names optional. Must match the number of columns in formulas
, "names":["1wk%","PE","SalesGr"]
, "pitMethod": 'Prelim' | 'Complete'
# use None for max precision
, "precision": None | 2 | 3 | 4
, "type": "stock" | "etf"
# add company name column
, "includeNames": False
, "figi": "Country Composite" | "Share Class"
, 'currency': 'USD' | 'CAD' | 'CHF' | 'EUR' | 'GBP' | 'NOK' | 'PLN' | 'SEK' | 'TRY'
# normalization
,"preproc": {
"scaling": "minmax" | "rank" | "normal"
, "scope" : "dataset" | "date"
, "trimPct": 5.0
, "outliers": True # when True outliers are clipped
, "naFill": False # when True NAs are set to the middle values
, "outlierLimit": 5 # used for normal scaling
# data license required for non technical factors
, "excludedFormulas": ["Close(0)/close(5)"]
# end date for the scaling when scope = dataset
, "mlTrainingEnd": "2020-01-01"
}
}
, to_pandas=True
)
Universe Functions
universe_update()
Wrapper for POST /universe
This operation updates the Universe used by API. This universe is always called "ApiUniverse" and it's stored in your account. If you don’t have this Universe already saved in the platform, it will be created.
p123api.Client().universe_update( {
'rules': ['rule1','rule2', ... ],
# optional parameters
'type': 'stock' | 'etf',
'currency': 'USD' | 'CAD' | 'CHF' | 'EUR' | 'GBP' | 'NOK' | 'PLN' | 'SEK' | 'TRY',
'startingUniverse': 'SP500' (optional)
})
Rank Functions
rank_ranks()
Wrapper for POST /rank/ranks
This operation allows you to retrieve rank data from a ranking system for a specific universe.
p123api.Client().rank_ranks({
'rankingSystem': 'Ranking name',
'asOfDt': 'yyyy-mm-dd',
'universe': 'Universe name',
#
# Optional parameters,
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
'rankingMethod': 2, # 2-Percentile NAs Negative, 4-Percentile NAs Neutral
# Filter for specific stocks
'tickers': 'IBM,MSFT',
'includeNames': False,
'includeNaCnt': False,
'includeFinalStmt': False,
'nodeDetails': 'composite' | 'factor',
'currency': 'USD' | 'CAD' | 'CHF' | 'EUR' | 'GBP' | 'NOK' | 'PLN' | 'SEK' | 'TRY',
'additionalData': ['formula1','formula2',...]
# Example: ['Close(0)', 'mktcap', "ZScore(`Pr2SalesQ`,#All)"]
},True) # True - output to Pandas DataFrame | [False] to JSON.
rank_perf()
Wrapper for POST /rank/performance
This operation lets you run bucket performance tests of multifactor ranking systems. You can use one of your existing ranking systems or a Portfolio123 ranking system. This includes your ApiRankingSystem which can be modified using the rank_update endpoint. Other specific settings include the number of buckets, minimum price, transaction slippage (expressed in %), sector, benchmark and output type.
p123api.Client().rank_perf({
'rankingSystem': 'Rank Name',
'startDt': 'yyyy-mm-dd',
#
# Optional parameters
'endDt': 'yyyy-mm-dd',
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
'universe': 'Universe name',
'transType': 'Long' | 'Short',
'rankingMethod': 2, # 2 NAs Negative | 4 NAs Neutral
'numBuckets': 10,
'minPrice': 5,
'minLiquidity': 5000,
'maxReturn': 200,
'rebalFreq': 'Every 4 Weeks' | 'Every Week' |
'Every N Weeks' (2,3,4,6,8,13,26,52),
'slippage': 0,
'benchmark': 'SPY',
'outputType': 'ann' | 'perf'
})
rank_update()
Wrapper for POST /rank
This operation updates the "API ranking system" called ApiRankingSystem. If you don’t have this ranking system already saved in the platform, it will be created automatically.
p123api.Client().rank_update({
# For 'nodes' use the same XML format you see when you
# click 'Text Editor' in the page Ranking System->Factors
'nodes': 'node definition',
'type': 'stock' | 'etf',
#
# Optional parameters
# ranking system id.
# If missing the ranking system 'ApiRankingSystem' is updated
'id': 123
'rankingMethod': 2, # 2 NAs Negative, 4 NAs Neutral
'currency': 'USD' | 'CAD' | 'CHF' | 'EUR' | 'GBP' | 'NOK' | 'PLN' | 'SEK' | 'TRY'
})
Screen Functions
screen_run()
Wrapper for POST /screen/run
This operation allows you to run a screen. You can specify the screen settings directly as well as use one of your existing screens.
# Specify the screen settings inline:
p123api.Client().screen_run({
'screen': {
'type': 'stock' | 'etf',
'universe': 'Universe name',
'maxNumHoldings': 10, # 0 for all
'method': 'long' | 'short' | 'long/short' | 'hedged',
'benchmark': 'SPY',
'currency': 'USD' | 'CAD' | 'CHF' | 'EUR' | 'GBP' | 'NOK' | 'PLN' | 'SEK' | 'TRY',
#Several options for specifying the ranking. Choose one of these 5:
'ranking': 'Ranking Name',
'ranking': id,
'ranking': {
'method': 0, # 0-Use Ranking System Default, 2-Percentile NAs Negative,
# 4-Percentile NAs Neutral, 1-Normal Distribution
'id': id},
'ranking': {
'method': 0,
'name': 'Ranking Name'},
'ranking': {
'formula': 'formula1',
'lowerIsBetter': True | False },
'rules': [
{'formula': 'formula1',
'type': 'common' | 'long' | 'short' | 'hedge'
},
{'formula': 'formula2',
'type': 'common' | 'long' | 'short' | 'hedge'
}
... etc ...]
#
# Optional parameters
'asOfDt': 'yyyy-mm-dd', # Defaults to today's date
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
},True) # True - output to Pandas DataFrame | [False] to JSON.
# Run an existing screen using the integer id of the screen:
p123api.Client().client.screen_run({
'screen': id,
#
# Optional parameters
'asOfDt': 'yyyy-mm-dd', # Defaults to today's date
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
},True) # True - output to Pandas DataFrame | [False] to JSON.
# Run an existing screen using the integer id of the screen and maxNumHoldings:
p123api.Client().client.screen_run({
'screen': {
'id': id,
'maxNumHoldings': 10 # 0 for all. Optional.
},
#
# Optional parameters
'asOfDt': 'yyyy-mm-dd', # Defaults to today's date
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4
},True) # True - output to Pandas DataFrame | [False] to JSON.
screen_backtest()
Wrapper for POST /screen/backtest
This operation allows you to run a performance backtest of a Screen.
# Backtest a screen which is defined inline:
p123api.Client().screen_backtest({
'screen': {
'type': 'stock' | 'etf',
'universe': 'Universe name',
'maxNumHoldings': 10, #0 for all
'method': 'long' | 'short' | 'long/short' | 'hedged',
'currency': 'USD' | 'CAD' | 'CHF' | 'EUR' | 'GBP' | 'NOK' | 'PLN' | 'SEK' | 'TRY',
'benchmark': 'SPY',
#Several options for specifying the ranking. Choose one of these 5:
'ranking': 'Ranking Name',
'ranking': id,
'ranking': {
'method': 0, # 0-Use Ranking System Default, 2-Percentile NAs Negative,
# 4-Percentile NAs Neutral, 1-Normal Distribution
'id': id},
'ranking': {
'method': 0,
'name': 'Ranking Name'},
'ranking': {
'formula': 'formula1',
'lowerIsBetter': True | False },
'rules': [
{'formula': 'formula1',
'type': 'common' | 'long' | 'short' | 'hedge'
},
{'formula': 'formula2',
'type': 'common' | 'long' | 'short' | 'hedge'
}
... etc ...]
},
'startDt': '2020-01-01',
#
# Optional parameters
'endDt': 'yyyy-mm-yy',
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
'transPrice': 1, # 1 - Open | 3 - Avg of Hi and Low | 4 - Close
'maxPosPct': 0,
'slippage': 0.25,
'longWeight': 100,
'shortWeight': 100,
'rankTolerance': 0,
'carryCost': 0,
'rebalFreq': 'Every 4 Weeks' | 'Every Week' |
'Every N Weeks' (2,3,4,6,8,13,26,52),
'riskStatsPeriod': ['Monthly'] | 'Weekly' | 'Daily'
},True) # True - output to Pandas DataFrame | [False] to JSON.
# Backtest and existing screen using the integer id of the screen:
p123api.Client().screen_backtest({
'screen': id,
'startDt': '2020-01-01',
#
# Optional parameters
'endDt': 'yyyy-mm-yy',
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
'transPrice': 1, # 1 - Open | 3 - Avg of Hi and Low | 4 - Close
'maxPosPct': 0,
'slippage': 0.25,
'longWeight': 100,
'shortWeight': 100,
'rankTolerance': 0,
'carryCost': 0,
'rebalFreq': 'Every 4 Weeks' | 'Every Week' |
'Every N Weeks' (2,3,4,6,8,13,26,52),
'riskStatsPeriod': 'Monthly' | 'Weekly' | 'Daily'
},True) # True - output to Pandas DataFrame | [False] to JSON.
# Backtest an existing screen using the integer id of the screen and maxNumHoldings:
p123api.Client().screen_backtest({
'screen': {
'id': id,
'maxNumHoldings': 10 # 0 for all. Optional.
},
'startDt': '2020-01-01',
#
# Optional parameters
'endDt': 'yyyy-mm-dd',
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
'transPrice': 1, # 1 - Open | 3 - Avg of Hi and Low | 4 - Close
'maxPosPct': 0,
'slippage': 0.25,
'longWeight': 100,
'shortWeight': 100,
'rankTolerance': 0,
'carryCost': 0,
'rebalFreq': 'Every 4 Weeks' | 'Every Week' |
'Every N Weeks' (2,3,4,6,8,13,26,52),
'riskStatsPeriod': ['Monthly'] | 'Weekly' | 'Daily'
},True) # True - output to Pandas DataFrame | [False] to JSON.
screen_rolling_backtest()
Wrapper for POST /screen/rolling-backtest
This operation allows you to run and collect the output of rolling screens. Rolling screens are subsequent, fixed holding period backtests of a screen, moving forward the starting date for each test. Rolling screens are excellent robustness tests.
p123api.Client().screen_rolling_backtest({
'screen': id,
'startDt': 'yyyy-mm-dd',
#
# Optional parameters
'endDt': 'yyyy-mm-dd',
'pitMethod': 'Prelim' | 'Complete',
'precision': 2 | 3 | 4,
'transPrice': 1, # 1 - Open | 3 - Avg of Hi and Low | 4 - Close
'maxPosPct': 0,
'slippage': 0.25,
'longWeight': 100,
'shortWeight': 100,
'frequency': 'Every 4 Weeks' | 'Every Week',
'holdingPeriod': 182
})
Strategy Functions
strategy()
Wrapper for GET /strategy/{id}
This operation returns the data from the Summary, Current Holdings and Statistics tabs of a strategies or books. The only parameter is the id of the strategy or book.
p123api.Client().strategy(
strategy_id=id
)
Data Series Functions
You can create and store a custom data series which consists of a list of dates and their associated values. You can then use these series in your rules as explained here . There are 3 operations to create or update, delete or upload data to a custom data series.
data_series_create_update()
Wrapper for POST /dataSeries
Create or update a data series. To create a new series omit the id parameter. The id of the newly created series is returned.
p123api.Client().data_series_create_update({
name : 'Name of Series',
# ID of the data series to update, omit to create new one
id : N,
# optional parameters
description : 'Series description optional'
})
data_series_delete()
Wrapper for DELETE /dataSeries/{id}
Deletes a data series and the data associated with it.
p123api.Client().data_series_delete(
series_id = N
)
data_series_upload()
Wrapper for POST /dataSeries/upload/{id}
Upload the series data. Data must be tabular with date and value in each row.
p123api.Client().data_series_upload(
file = 'C:/MyPath/SeriesData.csv',
series_id = id of series,
#
# Optional parameters
existing_data = 'overwrite' | 'skip' | 'delete',
date_format = 'yyyy-mm-dd' | 'yyyy/mm/dd' | 'mm/dd/yyyy' |
'mm-dd-yyyy' | 'dd/mm/yyyy' | 'dd-mm-yyyy' | 'dd.mm.yyyy',
decimal_separator = '.' | ',',
ignore_errors = False | True,
ignore_duplicates = False | True,
contains_header_row = False | True,
)
Stock Factors Functions
You can create and store a custom stock factor on the website which consists of a list of dates, tickers and their associated values.
stock_factor_create_update()
Wrapper for POST /stockFactor
Create or update a new stock factor. When the id is omitted a new factor will be created and the new id is returned.
p123api.Client().stock_factor_create_update({
'name': 'FactorName',
# Omit the id to create a new factor
'id' : id
# Optional parameters
'description': 'Description'
})
stock_factor_delete()
Wrapper for DELETE /stockFactor/{id}
Delete a stock factor.
p123api.Client().stock_factor_delete(
factor_id = id
)
stock_factor_upload()
Wrapper for POST /stockFactor/upload/{id}
Upload data from a csv file into an existing stock factor
p123api.Client().stock_factor_upload(
file = 'C:/MyPath/Factors.csv',
factor_id = id,
column_separator = 'comma' | 'semicolon' | 'tab',
existing_data = 'overwrite' | 'skip' | 'delete',
date_format = 'yyyy-mm-dd' | 'yyyy/mm/dd' | 'mm/dd/yyyy' |
'mm-dd-yyyy' | 'dd/mm/yyyy' | 'dd-mm-yyyy' | 'dd.mm.yyyy',
decimal_separator = '.' | ',',
ignore_errors = False | True,
ignore_duplicates = True | False
)
Did this answer your question?