Module scrilla.analysis.markets
A module of functions that calculate financial statistics.
Expand source code
# This file is part of scrilla: https://github.com/chinchalinchin/scrilla.
# scrilla is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3
# as published by the Free Software Foundation.
# scrilla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with scrilla. If not, see <https://www.gnu.org/licenses/>
# or <https://github.com/chinchalinchin/scrilla/blob/develop/main/LICENSE>.
"""
A module of functions that calculate financial statistics.
"""
import datetime
from typing import Dict, Union
from datetime import date
from scrilla import settings, services, files, cache, errors
from scrilla.static import keys
from scrilla.analysis.objects.cashflow import Cashflow
import scrilla.analysis.models.geometric.statistics as statistics
import scrilla.util.outputter as outputter
logger = outputter.Logger('scrilla.analysis.markets', settings.LOG_LEVEL)
profile_cache = cache.ProfileCache()
def sharpe_ratio(ticker: str, start_date: Union[date, None] = None, end_date: Union[date, None] = None, risk_free_rate: Union[float, None] = None, ticker_profile: Union[dict, None] = None, method: str = settings.ESTIMATION_METHOD) -> float:
"""
Calculates the sharpe ratio for the supplied ticker over the specified time range. If no start and end date are supplied, calculation will default to the last 100 days of prices. The risk free rate and ticker risk profile can be passed in to force calculations without historical data.
Parameters
----------
1. **ticker**: ``str``
A string of the ticker symbol whose sharpe ratio will be computed.
2. **start_date**: ``datetime.date``
Start date of the time period for which the sharpe ratio will be computed.
3. **end_date**: ``datetime.date``
End_date of the time period for which the sharpe ratio will be computed.
4. **risk_free_rate**: ``float``
Risk free rate used to evaluate excess return. Defaults to settings.RISK_FREE_RATE.
5. **ticker_profile**: ``dict``
Risk-return profile for the supplied ticker. Formatted as follows: `{ 'annual_return': float, 'annual_volatility': float } `
6. **method** : ``str``
Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary.
.. notes::
* if ``ticker_profile`` is provided, this function will skip both an external data service call and the calculation of the ticker's risk profile. The calculation will proceed as if the supplied profile were the true profile. If ``ticker_profile`` is not provided, all statistics will be estimated from historical data.
"""
start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date,
asset_type=keys.keys['ASSETS']['EQUITY'])
if ticker_profile is None:
result = profile_cache.filter_profile_cache(
ticker=ticker, start_date=start_date, end_date=end_date, method=method)
if result is not None and result[keys.keys['STATISTICS']['SHARPE']] is not None:
return result[keys.keys['STATISTICS']['SHARPE']]
ticker_profile = statistics.calculate_risk_return(
ticker=ticker, start_date=start_date, end_date=end_date, method=method)
if risk_free_rate is None:
risk_free_rate = services.get_risk_free_rate()
sh_ratio = (ticker_profile['annual_return'] -
risk_free_rate)/ticker_profile['annual_volatility']
profile_cache.save_or_update_row(ticker=ticker, start_date=start_date,
end_date=end_date, sharpe_ratio=sh_ratio, method=method)
return sh_ratio
# if no dates are specified, defaults to last 100 days
def market_premium(start_date: Union[date, None] = None, end_date: Union[date, None] = None, market_profile: Union[dict, None] = None, method: str = settings.ESTIMATION_METHOD) -> float:
"""
Returns the excess of the market return defined by the environment variable `MARKET_PROXY` over the risk free rate defined by the `RISK_FREE` environment variable.
Parameters
----------
1. **start_date**: ``datetime.date``
*Optional*. Start date of the time period for which the market premium will be computed. Defaults to 100 days ago.
2. **end_date**: ``datetime.date``
*Optional*. End_date of the time period for which the market premium will be computed. Defaults to today.
3. **market_profile**: ``dict``
*Optional*. Manually inputted market risk profile. Will override call to `scrilla.analysis.models.geometric.statistics.calculate_risk_return`.
4. **method** : ``str``
*Optional*. Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary.
"""
start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date,
asset_type=keys.keys['ASSETS']['EQUITY'])
if market_profile is None:
market_profile = statistics.calculate_risk_return(
ticker=settings.MARKET_PROXY, start_date=start_date, end_date=end_date, method=method)
market_prem = (
market_profile['annual_return'] - services.get_risk_free_rate())
return market_prem
def market_beta(ticker: str, start_date: Union[date, None] = None, end_date: Union[date, None] = None, market_profile: Union[dict, None] = None, market_correlation: Union[dict, None] = None, ticker_profile: Union[dict, None] = None, sample_prices: Union[dict, None] = None, method: str = settings.ESTIMATION_METHOD) -> float:
"""
Returns the beta of an asset against the market return defined by the ticker symbol set `scrilla.settings.MARKET_PROXY`, which in turn is configured through the environment variable of the same name, `MARKET_PROXY`.
Parameters
----------
1. **ticker**: ``str``
A string of the ticker symbol whose asset beta will be computed.
2. **start_date**: ``datetime.date``
Start date of the time period for which the asset beta will be computed.
3. **end_date**: ``datetime.date``
End_date of the time period for which the asset beta will be computed.
4. **method** : ``str``
Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary.
.. notes::
* If not configured by an environment variable, `scrilla.settings.MARKET_PROXY` defaults to ``SPY``, the ETF tracking the *S&P500*.
"""
start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date,
asset_type=keys.keys['ASSETS']['EQUITY'])
result = profile_cache.filter_profile_cache(
ticker=ticker, start_date=start_date, end_date=end_date, method=method)
if result is not None and result[keys.keys['STATISTICS']['BETA']] is not None:
return result[keys.keys['STATISTICS']['BETA']]
if market_profile is None:
if sample_prices is None:
market_profile = statistics.calculate_risk_return(ticker=settings.MARKET_PROXY, start_date=start_date,
end_date=end_date, method=method)
else:
market_profile = statistics.calculate_risk_return(ticker=settings.MARKET_PROXY, method=method,
sample_prices=sample_prices[settings.MARKET_PROXY])
if ticker_profile is None:
if sample_prices is None:
ticker_profile = statistics.calculate_risk_return(ticker=ticker, start_date=start_date,
end_date=end_date, method=method)
else:
ticker_profile = statistics.calculate_risk_return(ticker=ticker, method=method,
sample_prices=sample_prices[ticker])
market_covariance = statistics.calculate_return_covariance(ticker_1=ticker, ticker_2=settings.MARKET_PROXY,
profile_1=ticker_profile, profile_2=market_profile,
correlation=market_correlation,
sample_prices=sample_prices,
start_date=start_date, end_date=end_date)
beta = market_covariance / (market_profile['annual_volatility']**2)
profile_cache.save_or_update_row(
ticker=ticker, start_date=start_date, end_date=end_date, asset_beta=beta, method=method)
return beta
def cost_of_equity(ticker: str, start_date: Union[datetime.date, None] = None, end_date: Union[datetime.date, None] = None, market_profile: Union[Dict[str, float], None] = None, market_correlation: Union[Dict[str, float], None] = None, method=settings.ESTIMATION_METHOD) -> float:
"""
Returns the cost of equity of an asset as estimated by the Capital Asset Pricing Model, i.e. the product of the market premium and asset beta increased by the risk free rate.
Parameters
----------
1. **ticker**: ``str``
A string of the ticker symbol whose cost of equity ratio will be computed.
2. **start_date**: ``Union[datetime.date, None]``
*Optional*. Start date of the time period for which the cost of equity ratio will be computed
3. **end_date**: ``Union[datetime.date, None]``
*Optional.* End_date of the time period for which the cost of equity ratio will be computed.
4. **market_profile**: ``Union[Dict[str, float], None]``
*Optional*. Dictionary containing the assumed risk profile for the market proxy. Overrides calls to services and staistical methods, forcing the calculation fo the cost of equity with the inputted market profile. Format: ``{ 'annual_return': value, 'annual_volatility': value}``
5. **market_correlation**: ``Union[Dict[str, float], None]``
*Optional*. Dictionary containing the assumed correlation for the calculation. Overrides calls to services and statistical methods, forcing the calculation of the cost of equity with the inputted correlation. Format: ``{ 'correlation' : value }``
6. **method** : ``str``
*Optional*. Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary.
"""
start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date,
asset_type=keys.keys['ASSETS']['EQUITY'])
result = profile_cache.filter_profile_cache(
ticker=ticker, start_date=start_date, end_date=end_date, method=method)
if result is not None and result[keys.keys['STATISTICS']['EQUITY']] is not None:
return result[keys.keys['STATISTICS']['EQUITY']]
beta = market_beta(ticker=ticker, start_date=start_date, end_date=end_date,
market_profile=market_profile, market_correlation=market_correlation,
method=method)
premium = market_premium(start_date=start_date, end_date=end_date,
market_profile=market_profile, method=method)
equity_cost = (premium*beta + services.get_risk_free_rate())
profile_cache.save_or_update_row(
ticker=ticker, start_date=start_date, end_date=end_date, equity_cost=equity_cost, method=method)
return equity_cost
def screen_for_discount(model: str = keys.keys['MODELS']['DDM'], discount_rate: float = None) -> Dict[str, Dict[str, float]]:
"""
Screens the stocks saved under the user watchlist in the `scrilla.settings.COMMON_DIR` directory for discounts relative to the model inputted into the function.
Parameters
----------
1. **model** : ``str``
*Optional*. Model used to evaluated the equities saved in the watchlist. If no model is specified, the function will default to the discount dividend model. Model constants are accessible through the the `scrilla.keys.keys` dictionary.
2. **discount_rate** : ``float``
*Optional*. Rate used to discount future cashflows to present. Defaults to an equity's CAPM cost of equity, as calculated by `scrilla.analysis.markets.cost_of_equity`.
Returns
-------
``dict``
A list of tickers that trade at a discount relative to the model price, formatted as follows: `{ 'ticker' : { 'spot_price': value, 'model_price': value,'discount': value }, ... }`
"""
equities = list(files.get_watchlist())
discounts = {}
user_discount_rate = discount_rate
for equity in equities:
spot_price = services.get_daily_price_latest(ticker=equity)
if user_discount_rate is None:
discount_rate = cost_of_equity(ticker=equity)
else:
discount_rate = user_discount_rate
if model == keys.keys['MODELS']['DDM']:
logger.debug(
'Using Discount Dividend Model to screen watchlisted equities for discounts.')
dividends = services.get_dividend_history(equity)
model_price = Cashflow(
sample=dividends, discount_rate=discount_rate).calculate_net_present_value()
discount = float(model_price) - float(spot_price)
if discount > 0:
discount_result = {'spot_price': spot_price,
'model_price': model_price, 'discount': discount}
discounts[equity] = discount_result
logger.debug(f'Discount of {discount} found for {equity}')
return discounts
Functions
def cost_of_equity(ticker: str, start_date: Optional[datetime.date] = None, end_date: Optional[datetime.date] = None, market_profile: Optional[Dict[str, float]] = None, market_correlation: Optional[Dict[str, float]] = None, method='moments') ‑> float-
Returns the cost of equity of an asset as estimated by the Capital Asset Pricing Model, i.e. the product of the market premium and asset beta increased by the risk free rate.
Parameters
- ticker:
strA string of the ticker symbol whose cost of equity ratio will be computed. - start_date:
Union[datetime.date, None]Optional. Start date of the time period for which the cost of equity ratio will be computed - end_date:
Union[datetime.date, None]Optional. End_date of the time period for which the cost of equity ratio will be computed. - market_profile:
Union[Dict[str, float], None]Optional. Dictionary containing the assumed risk profile for the market proxy. Overrides calls to services and staistical methods, forcing the calculation fo the cost of equity with the inputted market profile. Format:{ 'annual_return': value, 'annual_volatility': value} - market_correlation:
Union[Dict[str, float], None]Optional. Dictionary containing the assumed correlation for the calculation. Overrides calls to services and statistical methods, forcing the calculation of the cost of equity with the inputted correlation. Format:{ 'correlation' : value } - method :
strOptional. Estimation method used to calculate financial statistics. Defaults to the value set byESTIMATION_METHOD. Allowable value are accessible through thescrilla.keys.keysdictionary.
Expand source code
def cost_of_equity(ticker: str, start_date: Union[datetime.date, None] = None, end_date: Union[datetime.date, None] = None, market_profile: Union[Dict[str, float], None] = None, market_correlation: Union[Dict[str, float], None] = None, method=settings.ESTIMATION_METHOD) -> float: """ Returns the cost of equity of an asset as estimated by the Capital Asset Pricing Model, i.e. the product of the market premium and asset beta increased by the risk free rate. Parameters ---------- 1. **ticker**: ``str`` A string of the ticker symbol whose cost of equity ratio will be computed. 2. **start_date**: ``Union[datetime.date, None]`` *Optional*. Start date of the time period for which the cost of equity ratio will be computed 3. **end_date**: ``Union[datetime.date, None]`` *Optional.* End_date of the time period for which the cost of equity ratio will be computed. 4. **market_profile**: ``Union[Dict[str, float], None]`` *Optional*. Dictionary containing the assumed risk profile for the market proxy. Overrides calls to services and staistical methods, forcing the calculation fo the cost of equity with the inputted market profile. Format: ``{ 'annual_return': value, 'annual_volatility': value}`` 5. **market_correlation**: ``Union[Dict[str, float], None]`` *Optional*. Dictionary containing the assumed correlation for the calculation. Overrides calls to services and statistical methods, forcing the calculation of the cost of equity with the inputted correlation. Format: ``{ 'correlation' : value }`` 6. **method** : ``str`` *Optional*. Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary. """ start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date, asset_type=keys.keys['ASSETS']['EQUITY']) result = profile_cache.filter_profile_cache( ticker=ticker, start_date=start_date, end_date=end_date, method=method) if result is not None and result[keys.keys['STATISTICS']['EQUITY']] is not None: return result[keys.keys['STATISTICS']['EQUITY']] beta = market_beta(ticker=ticker, start_date=start_date, end_date=end_date, market_profile=market_profile, market_correlation=market_correlation, method=method) premium = market_premium(start_date=start_date, end_date=end_date, market_profile=market_profile, method=method) equity_cost = (premium*beta + services.get_risk_free_rate()) profile_cache.save_or_update_row( ticker=ticker, start_date=start_date, end_date=end_date, equity_cost=equity_cost, method=method) return equity_cost - ticker:
def market_beta(ticker: str, start_date: Optional[datetime.date] = None, end_date: Optional[datetime.date] = None, market_profile: Optional[dict] = None, market_correlation: Optional[dict] = None, ticker_profile: Optional[dict] = None, sample_prices: Optional[dict] = None, method: str = 'moments') ‑> float-
Returns the beta of an asset against the market return defined by the ticker symbol set
MARKET_PROXY, which in turn is configured through the environment variable of the same name,MARKET_PROXY.Parameters
- ticker:
strA string of the ticker symbol whose asset beta will be computed. - start_date:
datetime.dateStart date of the time period for which the asset beta will be computed. - end_date:
datetime.dateEnd_date of the time period for which the asset beta will be computed. - method :
strEstimation method used to calculate financial statistics. Defaults to the value set byESTIMATION_METHOD. Allowable value are accessible through thescrilla.keys.keysdictionary.
Notes
- If not configured by an environment variable,
MARKET_PROXYdefaults toSPY, the ETF tracking the S&P500.
Expand source code
def market_beta(ticker: str, start_date: Union[date, None] = None, end_date: Union[date, None] = None, market_profile: Union[dict, None] = None, market_correlation: Union[dict, None] = None, ticker_profile: Union[dict, None] = None, sample_prices: Union[dict, None] = None, method: str = settings.ESTIMATION_METHOD) -> float: """ Returns the beta of an asset against the market return defined by the ticker symbol set `scrilla.settings.MARKET_PROXY`, which in turn is configured through the environment variable of the same name, `MARKET_PROXY`. Parameters ---------- 1. **ticker**: ``str`` A string of the ticker symbol whose asset beta will be computed. 2. **start_date**: ``datetime.date`` Start date of the time period for which the asset beta will be computed. 3. **end_date**: ``datetime.date`` End_date of the time period for which the asset beta will be computed. 4. **method** : ``str`` Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary. .. notes:: * If not configured by an environment variable, `scrilla.settings.MARKET_PROXY` defaults to ``SPY``, the ETF tracking the *S&P500*. """ start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date, asset_type=keys.keys['ASSETS']['EQUITY']) result = profile_cache.filter_profile_cache( ticker=ticker, start_date=start_date, end_date=end_date, method=method) if result is not None and result[keys.keys['STATISTICS']['BETA']] is not None: return result[keys.keys['STATISTICS']['BETA']] if market_profile is None: if sample_prices is None: market_profile = statistics.calculate_risk_return(ticker=settings.MARKET_PROXY, start_date=start_date, end_date=end_date, method=method) else: market_profile = statistics.calculate_risk_return(ticker=settings.MARKET_PROXY, method=method, sample_prices=sample_prices[settings.MARKET_PROXY]) if ticker_profile is None: if sample_prices is None: ticker_profile = statistics.calculate_risk_return(ticker=ticker, start_date=start_date, end_date=end_date, method=method) else: ticker_profile = statistics.calculate_risk_return(ticker=ticker, method=method, sample_prices=sample_prices[ticker]) market_covariance = statistics.calculate_return_covariance(ticker_1=ticker, ticker_2=settings.MARKET_PROXY, profile_1=ticker_profile, profile_2=market_profile, correlation=market_correlation, sample_prices=sample_prices, start_date=start_date, end_date=end_date) beta = market_covariance / (market_profile['annual_volatility']**2) profile_cache.save_or_update_row( ticker=ticker, start_date=start_date, end_date=end_date, asset_beta=beta, method=method) return beta - ticker:
-
Returns the excess of the market return defined by the environment variable
MARKET_PROXYover the risk free rate defined by theRISK_FREEenvironment variable.Parameters
- start_date:
datetime.dateOptional. Start date of the time period for which the market premium will be computed. Defaults to 100 days ago. - end_date:
datetime.dateOptional. End_date of the time period for which the market premium will be computed. Defaults to today. - market_profile:
dictOptional. Manually inputted market risk profile. Will override call tocalculate_risk_return(). - method :
strOptional. Estimation method used to calculate financial statistics. Defaults to the value set byESTIMATION_METHOD. Allowable value are accessible through thescrilla.keys.keysdictionary.
Expand source code
def market_premium(start_date: Union[date, None] = None, end_date: Union[date, None] = None, market_profile: Union[dict, None] = None, method: str = settings.ESTIMATION_METHOD) -> float: """ Returns the excess of the market return defined by the environment variable `MARKET_PROXY` over the risk free rate defined by the `RISK_FREE` environment variable. Parameters ---------- 1. **start_date**: ``datetime.date`` *Optional*. Start date of the time period for which the market premium will be computed. Defaults to 100 days ago. 2. **end_date**: ``datetime.date`` *Optional*. End_date of the time period for which the market premium will be computed. Defaults to today. 3. **market_profile**: ``dict`` *Optional*. Manually inputted market risk profile. Will override call to `scrilla.analysis.models.geometric.statistics.calculate_risk_return`. 4. **method** : ``str`` *Optional*. Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary. """ start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date, asset_type=keys.keys['ASSETS']['EQUITY']) if market_profile is None: market_profile = statistics.calculate_risk_return( ticker=settings.MARKET_PROXY, start_date=start_date, end_date=end_date, method=method) market_prem = ( market_profile['annual_return'] - services.get_risk_free_rate()) return market_prem - start_date:
def screen_for_discount(model: str = 'discount_dividend', discount_rate: float = None) ‑> Dict[str, Dict[str, float]]-
Screens the stocks saved under the user watchlist in the
COMMON_DIRdirectory for discounts relative to the model inputted into the function.Parameters
- model :
strOptional. Model used to evaluated the equities saved in the watchlist. If no model is specified, the function will default to the discount dividend model. Model constants are accessible through the thescrilla.keys.keysdictionary. - discount_rate :
floatOptional. Rate used to discount future cashflows to present. Defaults to an equity's CAPM cost of equity, as calculated bycost_of_equity().
Returns
dictA list of tickers that trade at a discount relative to the model price, formatted as follows:{ 'ticker' : { 'spot_price': value, 'model_price': value,'discount': value }, ... }Expand source code
def screen_for_discount(model: str = keys.keys['MODELS']['DDM'], discount_rate: float = None) -> Dict[str, Dict[str, float]]: """ Screens the stocks saved under the user watchlist in the `scrilla.settings.COMMON_DIR` directory for discounts relative to the model inputted into the function. Parameters ---------- 1. **model** : ``str`` *Optional*. Model used to evaluated the equities saved in the watchlist. If no model is specified, the function will default to the discount dividend model. Model constants are accessible through the the `scrilla.keys.keys` dictionary. 2. **discount_rate** : ``float`` *Optional*. Rate used to discount future cashflows to present. Defaults to an equity's CAPM cost of equity, as calculated by `scrilla.analysis.markets.cost_of_equity`. Returns ------- ``dict`` A list of tickers that trade at a discount relative to the model price, formatted as follows: `{ 'ticker' : { 'spot_price': value, 'model_price': value,'discount': value }, ... }` """ equities = list(files.get_watchlist()) discounts = {} user_discount_rate = discount_rate for equity in equities: spot_price = services.get_daily_price_latest(ticker=equity) if user_discount_rate is None: discount_rate = cost_of_equity(ticker=equity) else: discount_rate = user_discount_rate if model == keys.keys['MODELS']['DDM']: logger.debug( 'Using Discount Dividend Model to screen watchlisted equities for discounts.') dividends = services.get_dividend_history(equity) model_price = Cashflow( sample=dividends, discount_rate=discount_rate).calculate_net_present_value() discount = float(model_price) - float(spot_price) if discount > 0: discount_result = {'spot_price': spot_price, 'model_price': model_price, 'discount': discount} discounts[equity] = discount_result logger.debug(f'Discount of {discount} found for {equity}') return discounts - model :
def sharpe_ratio(ticker: str, start_date: Optional[datetime.date] = None, end_date: Optional[datetime.date] = None, risk_free_rate: Optional[float] = None, ticker_profile: Optional[dict] = None, method: str = 'moments') ‑> float-
Calculates the sharpe ratio for the supplied ticker over the specified time range. If no start and end date are supplied, calculation will default to the last 100 days of prices. The risk free rate and ticker risk profile can be passed in to force calculations without historical data.
Parameters
- ticker:
strA string of the ticker symbol whose sharpe ratio will be computed. - start_date:
datetime.dateStart date of the time period for which the sharpe ratio will be computed. - end_date:
datetime.dateEnd_date of the time period for which the sharpe ratio will be computed. - risk_free_rate:
floatRisk free rate used to evaluate excess return. Defaults to settings.RISK_FREE_RATE. - ticker_profile:
dictRisk-return profile for the supplied ticker. Formatted as follows:{ 'annual_return': float, 'annual_volatility': float } - method :
strEstimation method used to calculate financial statistics. Defaults to the value set byESTIMATION_METHOD. Allowable value are accessible through thescrilla.keys.keysdictionary.
Notes
- if
ticker_profileis provided, this function will skip both an external data service call and the calculation of the ticker's risk profile. The calculation will proceed as if the supplied profile were the true profile. Ifticker_profileis not provided, all statistics will be estimated from historical data.
Expand source code
def sharpe_ratio(ticker: str, start_date: Union[date, None] = None, end_date: Union[date, None] = None, risk_free_rate: Union[float, None] = None, ticker_profile: Union[dict, None] = None, method: str = settings.ESTIMATION_METHOD) -> float: """ Calculates the sharpe ratio for the supplied ticker over the specified time range. If no start and end date are supplied, calculation will default to the last 100 days of prices. The risk free rate and ticker risk profile can be passed in to force calculations without historical data. Parameters ---------- 1. **ticker**: ``str`` A string of the ticker symbol whose sharpe ratio will be computed. 2. **start_date**: ``datetime.date`` Start date of the time period for which the sharpe ratio will be computed. 3. **end_date**: ``datetime.date`` End_date of the time period for which the sharpe ratio will be computed. 4. **risk_free_rate**: ``float`` Risk free rate used to evaluate excess return. Defaults to settings.RISK_FREE_RATE. 5. **ticker_profile**: ``dict`` Risk-return profile for the supplied ticker. Formatted as follows: `{ 'annual_return': float, 'annual_volatility': float } ` 6. **method** : ``str`` Estimation method used to calculate financial statistics. Defaults to the value set by `scrilla.settings.ESTIMATION_METHOD`. Allowable value are accessible through the `scrilla.keys.keys` dictionary. .. notes:: * if ``ticker_profile`` is provided, this function will skip both an external data service call and the calculation of the ticker's risk profile. The calculation will proceed as if the supplied profile were the true profile. If ``ticker_profile`` is not provided, all statistics will be estimated from historical data. """ start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date, asset_type=keys.keys['ASSETS']['EQUITY']) if ticker_profile is None: result = profile_cache.filter_profile_cache( ticker=ticker, start_date=start_date, end_date=end_date, method=method) if result is not None and result[keys.keys['STATISTICS']['SHARPE']] is not None: return result[keys.keys['STATISTICS']['SHARPE']] ticker_profile = statistics.calculate_risk_return( ticker=ticker, start_date=start_date, end_date=end_date, method=method) if risk_free_rate is None: risk_free_rate = services.get_risk_free_rate() sh_ratio = (ticker_profile['annual_return'] - risk_free_rate)/ticker_profile['annual_volatility'] profile_cache.save_or_update_row(ticker=ticker, start_date=start_date, end_date=end_date, sharpe_ratio=sh_ratio, method=method) return sh_ratio - ticker: