Skip to content

Commit

Permalink
testing out sqlite caching, adjusting queries and result formatting t…
Browse files Browse the repository at this point in the history
…o be consistent with how applicaiton expects date to be structured, add caches for all calculations, abstract stat manager and div manager into new classes
  • Loading branch information
chinchalinchin committed Sep 13, 2021
1 parent 70d7e01 commit ea5e07c
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 138 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,12 @@ The four functions of interest in this module are:
<b>Returns:</b><br>
a dictionary of prices with the `YYYY-MM-DD` formatted date as key. The dictionary is sorted latest price to earliest price.<br>

2. `scrilla.services.get_daily_stat_history(statistic, start_date=None, end_date=None)`<br>
2. `scrilla.services.get_daily_stat_history(symbol, start_date=None, end_date=None)`<br>
<b>Description:</b><br>
This function will retrieve the price history for the financial statistic specifed by the `statistic` argument.
<br><br>
<b>Arguments:</b><br>
- `statistic : str`: Required. Statistic symbol for quantity of interest. A list of allowable values can be found [here](https://www.quandl.com/data/FRED-Federal-Reserve-Economic-Data/documentation)<br>
- `symbol : str`: Required. Statistic symbol for quantity of interest. A list of allowable values can be found [here](https://www.quandl.com/data/FRED-Federal-Reserve-Economic-Data/documentation)<br>
- `start_date: datetime.date` : Optional. Start date of analysis range. Defaults to `None`<br>
- `end_date: datetime.date` : Optional. End date of analysis range. Defaults to `None`<br>

Expand Down
26 changes: 19 additions & 7 deletions src/scrilla/analysis/markets.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,21 @@ def sharpe_ratio(ticker, start_date=None, end_date=None, risk_free_rate=None, ti
Risk-return profile for the supplied ticker. If provided, start_date and end_date are ignored and the values in ticker_profile are used to calculate the Sharpe ratio.
"""
try:
start_date, end_date = errors.validate_dates(start_date=start_date, end_date=end_date,
asset_type=static.keys['ASSETS']['EQUITY'])
except errors.InputValidationError as ive:
raise ive

print('inside markets.sharpe_ratio')
result = profile_cache.filter_profile_cache(ticker=ticker, start_date=start_date, end_date=end_date)

if result[static.keys['STATISTICS']['SHARPE']] is not None:
return result
print('result', result)
if result is not None and result[static.keys['STATISTICS']['SHARPE']] is not None:
return result[static.keys['STATISTICS']['SHARPE']]

if ticker_profile is None:
if ticker_profile is None:
print('calcuatling rr from markets.sharpe_ratio')
ticker_profile = statistics.calculate_risk_return(ticker=ticker, start_date=start_date,
end_date=end_date)

Expand All @@ -51,6 +59,7 @@ def sharpe_ratio(ticker, start_date=None, end_date=None, risk_free_rate=None, ti

sharpe_ratio = (ticker_profile['annual_return'] - risk_free_rate)/ticker_profile['annual_volatility']

print('RRRRRRIGGGHHHHTTT FUCKING HERE!!!')
profile_cache.save_or_update_row(ticker=ticker, start_date=start_date,
end_date=end_date,sharpe_ratio=sharpe_ratio)

Expand Down Expand Up @@ -131,8 +140,8 @@ def market_beta(ticker, start_date=None, end_date=None, market_profile=None, mar

result = profile_cache.filter_profile_cache(ticker=ticker, start_date=start_date, end_date=end_date)

if result['STATISTICS']['BETA'] is not None:
return result
if result is not None and result[static.keys['STATISTICS']['BETA']] is not None:
return result[static.keys['STATISTICS']['BETA']]

try:
if market_profile is None:
Expand Down Expand Up @@ -195,8 +204,8 @@ def cost_of_equity(ticker, start_date=None, end_date=None, market_profile=None,

result = profile_cache.filter_profile_cache(ticker=ticker, start_date=start_date, end_date=end_date)

if result['STATISTICS']['EQUITY'] is not None:
return result
if result is not None and result[static.keys['STATISTICS']['EQUITY']] is not None:
return result[static.keys['STATISTICS']['EQUITY']]

try:
beta = market_beta(ticker=ticker, start_date=start_date, end_date=end_date,
Expand All @@ -209,6 +218,9 @@ def cost_of_equity(ticker, start_date=None, end_date=None, market_profile=None,
except errors.APIResponseError as api:
raise api

print('prem', premium)
print('beta', beta)
print('risk_free', services.get_risk_free_rate())
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)
Expand Down
28 changes: 18 additions & 10 deletions src/scrilla/analysis/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,11 @@ def calculate_risk_return(ticker, start_date=None, end_date=None, sample_prices=
1. ticker : str \n
Required. Ticker symbol whose risk-return profile is to be calculated. \n \n
2. start_date : datetime.date \n
Optional. Start date of the time period over which the risk-return profile is to be calculated. Defaults to `None`, in which case the calculation proceeds as if `start_date` were set to 100 trading days prior to `end_date`. If `get_asset_type(ticker)=static.keys['ASSET']['CRYPTO']`, this means 100 days regardless. If `get_asset_type(ticker)=static.keys['ASSET']['EQUITY']`, this excludes weekends and holidays and decrements the `end_date` by 100 trading days.\n \n
Optional. Start date of the time period over which the risk-return profile is to be calculated. Defaults to `None`, in which case the calculation proceeds as if `start_date` were set to 100 trading days prior to `end_date`. If `get_asset_type(ticker)=static.keys['ASSETS']['CRYPTO']`, this means 100 days regardless. If `get_asset_type(ticker)=static.keys['ASSETS']['EQUITY']`, this excludes weekends and holidays and decrements the `end_date` by 100 trading days.\n \n
3. end_date : datetime.date \n
Optional. End date of the time period over which the risk-return profile is to be calculated. Defaults to `None`, in which the calculation proceeds as if `end_date` were set to today. If the `get_asset_type(ticker)==static.keys['ASSETS']['CRYPTO']` this means today regardless. If `get_asset_type(ticker)=static.keys['ASSET']['EQUITY']` this excludes holidays and weekends and sets the end date to the last valid trading date. \n \n
4. sample_prices : { 'date' (str) : 'price' (str) } \n
Optional. A list of the asset prices for which correlation will be calculated. Overrides calls to service and calculates correlation for sample of prices supplied. Function will disregard start_date and end_date if sample_price is specified: { 'date_1' : { 'open' : number, 'close' : number}, 'date_2': { 'open': number, 'close': number} ... } and ordered from latest date to earliest date. \n \n
Optional. End date of the time period over which the risk-return profile is to be calculated. Defaults to `None`, in which the calculation proceeds as if `end_date` were set to today. If the `get_asset_type(ticker)==static.keys['ASSETS']['CRYPTO']` this means today regardless. If `get_asset_type(ticker)=static.keys['ASSETS']['EQUITY']` this excludes holidays and weekends and sets the end date to the last valid trading date. \n \n
4. sample_prices : { 'date_1' : { 'open' : number, 'close' : number}, 'date_2': { 'open': number, 'close': number} ... } \n
Optional. A list of the asset prices for which correlation will be calculated. Overrides calls to service and forces calculation of correlation for sample of prices supplied. Function will disregard `start_date` and `end_date` and use the first and last key as the latest and earliest date, respectively. In other words, the `sample_prices` dictionary must be ordered from latest to earliest. \n \n
5. asset_type : str
Optional. Specify asset type to prevent overusing redundant calculations. Allowable values: settings.ASSET_TYPE_EQUITY, settings.ASSET_TYPE_CRYPTO \n \n
Expand Down Expand Up @@ -535,9 +535,12 @@ def calculate_risk_return(ticker, start_date=None, end_date=None, sample_prices=
except errors.InputValidationError as ive:
raise ive

print('inside statistics.calculate_risk_return')
results = profile_cache.filter_profile_cache(ticker=ticker, start_date=start_date, end_date=end_date)

if results[static.keys['STATISTICS']['RETURN']] is not None \
print('results', results)
if results is not None \
and results[static.keys['STATISTICS']['RETURN']] is not None \
and results[static.keys['STATISTICS']['VOLATILITY']] is not None:
return results

Expand All @@ -549,13 +552,18 @@ def calculate_risk_return(ticker, start_date=None, end_date=None, sample_prices=
else:
logger.debug(f'{ticker} sample prices provided, skipping service call.')
prices = sample_prices
try:
asset_type = errors.validate_asset_type(ticker, asset_type)
trading_period = static.get_trading_period(asset_type)
except errors.InputValidationError as ive:
raise ive

if not prices:
raise errors.PriceError(f'No prices could be retrieved for {ticker}')

# Log of difference loses a sample
sample = len(prices) - 1
logger.debug(f'Calculating mean annual return over last {sample+1} days for {ticker}')
logger.debug(f'Calculating mean annual return over last {sample} days for {ticker}')

### MEAN CALCULATION
# NOTE: mean return is a telescoping series, i.e. sum of log(x1/x0) only depends on the first and
Expand All @@ -571,7 +579,7 @@ def calculate_risk_return(ticker, start_date=None, end_date=None, sample_prices=
today, variance, tomorrows_price, tomorrows_date = False, 0, 0, None
# adjust the random variable being measured so expectation is easier to calculate.
mean_mod_return = mean_return*sqrt(trading_period)
logger.debug(f'Calculating mean annual volatility over last {sample+1} days for {ticker}')
logger.debug(f'Calculating mean annual volatility over last {sample} days for {ticker}')

for date in prices:
todays_price = prices[date][static.keys['PRICES']['CLOSE']]
Expand Down Expand Up @@ -682,9 +690,9 @@ def calculate_ito_correlation(ticker_1, ticker_2, asset_type_1=None, asset_type_
raise api

if (len(sample_prices[ticker_1]) == 0) \
or (len(sample_prices[ticker_2]) == 0 \
or len(sample_prices[ticker_1]) != len(sample_prices[ticker_2]) \
or len(helper.intersect_dict_keys(sample_prices[ticker_1], sample_prices[ticker_2]) == 0)):
or (len(sample_prices[ticker_2]) == 0) \
or (len(sample_prices[ticker_1]) != len(sample_prices[ticker_2])) \
or (len(helper.intersect_dict_keys(sample_prices[ticker_1], sample_prices[ticker_2])) == 0):
raise errors.PriceError("Prices cannot be retrieved for correlation calculation")

if asset_type_1 != asset_type_2:
Expand Down
Loading

0 comments on commit ea5e07c

Please sign in to comment.