概要
QuantConnect平台上多因子选股的一个实现,出处。
整体架构流程
前置环境:
- VS2022 Community(Python和C#选上)
- Anaconda3-2020.11-Windows-x86_64(升级Python到3.8.13,环境变量关联到pythonnet)
- Docker Desktop(下载research 16863版本镜像)
- VS Code
- Github Lean 16863版本(注意修改镜像为research 16863)
数据准备:
- 随机生成1000个股行情数据
- 配套1000个股生成基本面数据
技术细节
- 文件夹Lean-16863\Algorithm.Python\FactorInvesting
│ Factor Investing In QuantConnect - Research Notebook & Backtesting Algorithm.mhtml
│ main.py
│ research.ipynb
│ ResearchFactorAnalysis.py
│ ResearchRiskAnalysis.py
│ tree.txt
│
├─Alpha
│ │ LongShortAlphaCreation.py
│ │
│ └─__pycache__
│ LongShortAlphaCreation.cpython-311.pyc
│
├─Helpers
│ │ classSymbolData.py
│ │ HelperFunctions.py
│ │
│ └─__pycache__
│ classSymbolData.cpython-311.pyc
│ HelperFunctions.cpython-311.pyc
│
├─Portfolio
│ │ CustomEqualWeightingPortfolioConstruction.py
│ │
│ └─__pycache__
│ CustomEqualWeightingPortfolioConstruction.cpython-311.pyc
│
├─Universe
│ │ FactorModelUniverseSelection.py
│ │
│ └─__pycache__
│ FactorModelUniverseSelection.cpython-311.pyc
│
└─__pycache__
main.cpython-311.pyc
- LongShortAlphaCreation.py
# region imports
from AlgorithmImports import *
# endregion
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Alphas import AlphaModel, Insight, InsightType, InsightDirection
from Helpers.HelperFunctions import GetFundamentalDataDict, MakeCalculations, GetLongShortLists
from datetime import timedelta, datetime
import pandas as pd
import numpy as np
class LongShortAlphaCreationModel(AlphaModel):
def __init__(self, maxNumberOfPositions = 10, lookback = 252):
self.maxNumberOfPositions = maxNumberOfPositions
self.lookback = lookback
self.securities = []
self.day = 0
def Update(self, algorithm, data):
insights = [] # list to store the new insights to be created
if algorithm.Time.day != self.day and algorithm.Time.hour > 9:
for symbol, direction in self.insightsDict.items():
if data.ContainsKey(symbol) and symbol in algorithm.ActiveSecurities.Keys and algorithm.ActiveSecurities[symbol].Price > 0:
insights.append(Insight.Price(symbol, Expiry.EndOfDay, direction))
self.day = algorithm.Time.day
return insights
def OnSecuritiesChanged(self, algorithm, changes):
'''
Description:
Event fired each time the we add/remove securities from the data feed
Args:
algorithm: The algorithm instance that experienced the change in securities
changes: The security additions and removals from the algorithm
'''
# check current securities in our self.securities list
securitiesList = [x.Symbol.Value for x in self.securities]
algorithm.Log('(Alpha module) securities in self.securities before OnSecuritiesChanged: ' + str(securitiesList))
# add new securities
addedSecurities = [x for x in changes.AddedSecurities if x not in self.securities]
for added in addedSecurities:
self.securities.append(added)
newSecuritiesList = [x.Symbol.Value for x in addedSecurities]
algorithm.Log('(Alpha module) new securities added to self.securities:'+ str(newSecuritiesList))
# remove securities
removedSecurities = [x for x in changes.RemovedSecurities if x in self.securities]
for removed in removedSecurities:
self.securities.remove(removed)
removedList = [x.Symbol.Value for x in removedSecurities]
algorithm.Log('(Alpha module) securities removed from self.securities: ' + str(removedList))
# print the final securities in self.securities for today
securitiesList = [x.Symbol.Value for x in self.securities]
algorithm.Log('(Alpha module) final securities in self.securities after OnSecuritiesChanged: ' + str(securitiesList))
# generate dictionary with factors -------------------------------------------------------
fundamentalDataBySymbolDict = GetFundamentalDataDict(algorithm, self.securities, module = 'alpha')
# make calculations to create long/short lists -------------------------------------------
currentSymbols = list(fundamentalDataBySymbolDict.keys())
calculations = MakeCalculations(algorithm, currentSymbols, self.lookback, Resolution.Daily, fundamentalDataBySymbolDict)
# get long/short lists
longs, shorts = GetLongShortLists(self, algorithm, calculations)
finalSymbols = longs + shorts
# update the insightsDict dictionary with long/short signals
self.insightsDict = {}
for symbol in finalSymbols:
if symbol in longs:
direction = 1
else:
direction = -1
self.insightsDict[symbol] = direction
- classSymbolData.py
# region imports
from AlgorithmImports import *
# endregion
import pandas as pd
import numpy as np
from scipy.stats import skew, kurtosis
class SymbolData:
''' Perform calculations '''
def __init__(self, symbol):
self.Symbol = symbol
self.fundamentalDataDict = {}
self.momentum = None
self.volatility = None
self.skewness = None
self.kurt = None
self.positionVsHL = None
self.meanOvernightReturns = None
def CalculateFactors(self, history, fundamentalDataBySymbolDict):
self.fundamentalDataDict = fundamentalDataBySymbolDict[self.Symbol]
self.momentum = self.CalculateMomentum(history)
self.volatility = self.CalculateVolatility(history)
#self.skewness = self.CalculateSkewness(history)
#self.kurt = self.CalculateKurtosis(history)
#self.distanceVsHL = self.CalculateDistanceVsHL(history)
#self.meanOvernightReturns = self.CalculateMeanOvernightReturns(history)
def CalculateMomentum(self, history):
closePrices = history.loc[self.Symbol]['close']
momentum = (closePrices[-1] / closePrices[-252]) - 1
return momentum
def CalculateVolatility(self, history):
closePrices = history.loc[self.Symbol]['close']
returns = closePrices.pct_change().dropna()
volatility = np.nanstd(returns, axis = 0)
return volatility
def CalculateSkewness(self, history):
closePrices = history.loc[self.Symbol]['close']
returns = closePrices.pct_change().dropna()
skewness = skew(returns)
return skewness
def CalculateKurtosis(self, history):
closePrices = history.loc[self.Symbol]['close']
returns = closePrices.pct_change().dropna()
kurt = kurtosis(returns)
return kurt
def CalculateDistanceVsHL(self, history):
closePrices = history.loc[self.Symbol]['close']
annualHigh = max(closePrices)
annualLow = min(closePrices)
distanceVsHL = (closePrices[-1] - annualLow) / (annualHigh - annualLow)
return distanceVsHL
def CalculateMeanOvernightReturns(self, history):
overnnightReturns = (history.loc[self.Symbol]['open'] / history.loc[self.Symbol]['close'].shift(1)) - 1
meanOvernightReturns = np.nanmean(overnnightReturns, axis = 0)
return meanOvernightReturns
@property
def factorsList(self):
technicalFactors = [self.momentum, self.volatility]
fundamentalFactors = [float(key) * value for key, value in self.fundamentalDataDict.items()]
if all(v is not None for v in technicalFactors):
return technicalFactors + fundamentalFactors
else:
return None
- HelperFunctions.py
# region imports
from AlgorithmImports import *
# endregion
import pandas as pd
from scipy.stats import zscore
from Helpers.classSymbolData import SymbolData
def MakeCalculations(algorithm, symbols, lookback, resolution, fundamentalDataBySymbolDict):
'''
Description:
Make required calculations using historical data for each symbol
Args:
symbols: The symbols to make calculations for
lookback: Lookback period for historical data
resolution: Resolution for historical data
fundamentalDataBySymbolDict: Dictionary of symbols containing factors and the direction of the factor (for sorting)
Return:
calculations: Dictionary containing the calculations per symbol
'''
# store calculations
calculations = {}
if len(symbols) > 0:
# get historical prices for new symbols
history = GetHistory(algorithm, symbols,
lookbackPeriod = lookback,
resolution = resolution)
for symbol in symbols:
# if symbol has no historical data continue the loop
if (symbol not in history.index
or len(history.loc[symbol]['close']) < lookback
or history.loc[symbol].get('close') is None
or history.loc[symbol].get('close').isna().any()):
algorithm.Log('no history found for: ' + str(symbol.Value))
continue
else:
# add symbol to calculations
calculations[symbol] = SymbolData(symbol)
try:
calculations[symbol].CalculateFactors(history, fundamentalDataBySymbolDict)
except Exception as e:
algorithm.Log('removing from calculations due to ' + str(e))
calculations.pop(symbol)
continue
return calculations
def GetFundamentalDataDict(algorithm, securitiesData, module = 'universe'):
''' Create a dictionary of symbols and fundamental factors ready for sorting '''
fundamentalDataBySymbolDict = {}
# loop through data and get fundamental data
for x in securitiesData:
if module == 'alpha':
if not x.Symbol in algorithm.ActiveSecurities.Keys:
continue
fundamental = algorithm.ActiveSecurities[x.Symbol].Fundamentals
elif module == 'universe':
fundamental = x
else:
raise ValueError('module argument must be either universe or alpha')
# dictionary of symbols containing factors and the direction of the factor (1 for sorting descending and -1 for sorting ascending)
fundamentalDataBySymbolDict[x.Symbol] = {
#fundamental.ValuationRatios.BookValuePerShare: 1,
#fundamental.FinancialStatements.BalanceSheet.TotalEquity.Value: -1,
#fundamental.OperationRatios.OperationMargin.Value: 1,
#fundamental.OperationRatios.ROE.Value: 1,
#fundamental.OperationRatios.TotalAssetsGrowth.Value: 1,
#fundamental.ValuationRatios.PERatio: 1
}
# check validity of data
if None in list(fundamentalDataBySymbolDict[x.Symbol].keys()):
fundamentalDataBySymbolDict.pop(x.Symbol)
return fundamentalDataBySymbolDict
def GetLongShortLists(self, algorithm, calculations):
''' Create lists of long/short stocks '''
# get factors
factorsDict = { symbol: symbolData.factorsList for symbol, symbolData in calculations.items() if symbolData.factorsList is not None }
factorsDf = pd.DataFrame.from_dict(factorsDict, orient = 'index')
# normalize factor
normFactorsDf = factorsDf.apply(zscore)
normFactorsDf.columns = ['Factor_' + str(x + 1) for x in normFactorsDf.columns]
# combine factors using equal weighting
#normFactorsDf['combinedFactor'] = normFactorsDf.sum(axis = 1)
normFactorsDf['combinedFactor'] = normFactorsDf['Factor_1'] * 1 + normFactorsDf['Factor_2'] * 1
# sort descending
sortedNormFactorsDf = normFactorsDf.sort_values(by = 'combinedFactor', ascending = False) # descending
# create long/short lists
positionsEachSide = int(self.maxNumberOfPositions / 2)
longs = list(sortedNormFactorsDf[:positionsEachSide].index)
shorts = list(sortedNormFactorsDf[-positionsEachSide:].index)
shorts = [x for x in shorts if x not in longs]
return longs, shorts
def GetHistory(algorithm, symbols, lookbackPeriod, resolution):
''' Pull historical data in batches '''
total = len(symbols)
batchsize = 50
if total <= batchsize:
history = algorithm.History(symbols, lookbackPeriod, resolution)
else:
history = algorithm.History(symbols[0:batchsize], lookbackPeriod, resolution)
for i in range(batchsize, total + 1, batchsize):
batch = symbols[i:(i + batchsize)]
historyTemp = algorithm.History(batch, lookbackPeriod, resolution)
history = pd.concat([history, historyTemp])
return history
def UpdateBenchmarkValue(self, algorithm):
''' Simulate buy and hold the Benchmark '''
if self.initBenchmarkPrice == 0:
self.initBenchmarkCash = algorithm.Portfolio.Cash
self.initBenchmarkPrice = algorithm.Benchmark.Evaluate(algorithm.Time)
self.benchmarkValue = self.initBenchmarkCash
else:
currentBenchmarkPrice = algorithm.Benchmark.Evaluate(algorithm.Time)
self.benchmarkValue = (currentBenchmarkPrice / self.initBenchmarkPrice) * self.initBenchmarkCash
def UpdatePlots(self, algorithm):
''' Update Portfolio Exposure and Drawdown plots '''
# simulate buy and hold the benchmark and plot its daily value --------------
UpdateBenchmarkValue(self, algorithm)
algorithm.Plot('Strategy Equity', self.benchmark, self.benchmarkValue)
# get current portfolio value
currentTotalPortfolioValue = algorithm.Portfolio.TotalPortfolioValue
# plot the daily total portfolio exposure % --------------------------------
longHoldings = sum([x.HoldingsValue for x in algorithm.Portfolio.Values if x.IsLong])
shortHoldings = sum([x.HoldingsValue for x in algorithm.Portfolio.Values if x.IsShort])
totalHoldings = longHoldings + shortHoldings
totalPortfolioExposure = (totalHoldings / currentTotalPortfolioValue) * 100
algorithm.Plot('Chart Total Portfolio Exposure %', 'Daily Portfolio Exposure %', totalPortfolioExposure)
# plot the daily number of longs and shorts --------------------------------
nLongs = sum(x.IsLong for x in algorithm.Portfolio.Values)
nShorts = sum(x.IsShort for x in algorithm.Portfolio.Values)
algorithm.Plot('Chart Number Of Longs/Shorts', 'Daily N Longs', nLongs)
algorithm.Plot('Chart Number Of Longs/Shorts', 'Daily N Shorts', nShorts)
# plot the drawdown % from the most recent high ---------------------------
if not self.portfolioValueHighInitialized:
self.portfolioHigh = currentTotalPortfolioValue # set initial portfolio value
self.portfolioValueHighInitialized = True
# update trailing high value of the portfolio
if self.portfolioValueHigh < currentTotalPortfolioValue:
self.portfolioValueHigh = currentTotalPortfolioValue
currentDrawdownPercent = ((float(currentTotalPortfolioValue) / float(self.portfolioValueHigh)) - 1.0) * 100
algorithm.Plot('Chart Drawdown %', 'Drawdown %', currentDrawdownPercent)
- CustomEqualWeightingPortfolioConstruction.py
# region imports
from AlgorithmImports import *
# endregion
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm.Framework")
from QuantConnect import Resolution, Extensions
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from itertools import groupby
from datetime import datetime, timedelta
class CustomEqualWeightingPortfolioConstructionModel(PortfolioConstructionModel):
'''
Description:
Provide a custom implementation of IPortfolioConstructionModel that gives equal weighting to all active securities
Details:
- The target percent holdings of each security is 1/N where N is the number of securities with active Up/Down insights
- For InsightDirection.Up, long targets are returned
- For InsightDirection.Down, short targets are returned
- For InsightDirection.Flat, closing position targets are returned
'''
def __init__(self, initialAllocationPerSecurity = 0.1, rebalancingFunc = Expiry.EndOfMonth):
'''
Description:
Initialize a new instance of CustomEqualWeightingPortfolioConstructionModel
Args:
initialAllocationPerSecurity: Portfolio exposure per security (as a % of total equity)
'''
# portfolio exposure per security (as a % of total equity)
self.initialAllocationPerSecurity = initialAllocationPerSecurity
self.rebalancingFunc = rebalancingFunc
self.insightCollection = InsightCollection()
self.removedSymbols = []
self.nextRebalance = None
def CreateTargets(self, algorithm, insights):
'''
Description:
Create portfolio targets from the specified insights
Args:
algorithm: The algorithm instance
insights: The insights to create portfolio targets from
Returns:
An enumerable of portfolio targets to be sent to the execution model
'''
targets = []
if len(insights) == 0:
return targets
# apply rebalancing logic
if self.nextRebalance is not None and algorithm.Time < self.nextRebalance and len(self.removedSymbols) == 0:
return targets
self.nextRebalance = self.rebalancingFunc(algorithm.Time)
# here we get the new insights and add them to our insight collection
for insight in insights:
self.insightCollection.Add(insight)
# create flatten target for each security that was removed from the universe
if len(self.removedSymbols) > 0:
universeDeselectionTargets = [ PortfolioTarget(symbol, 0) for symbol in self.removedSymbols ]
targets.extend(universeDeselectionTargets)
algorithm.Log('(Portfolio module) liquidating: ' + str([x.Value for x in self.removedSymbols]))
self.removedSymbols = []
# get insight that have not expired of each symbol that is still in the universe
activeInsights = self.insightCollection.GetActiveInsights(algorithm.UtcTime)
# get the last generated active insight for each symbol
lastActiveInsights = []
for symbol, g in groupby(activeInsights, lambda x: x.Symbol):
lastActiveInsights.append(sorted(g, key = lambda x: x.GeneratedTimeUtc)[-1])
# determine target percent for the given insights
for insight in lastActiveInsights:
allocationPercent = self.initialAllocationPerSecurity * insight.Direction
target = PortfolioTarget.Percent(algorithm, insight.Symbol, allocationPercent)
targets.append(target)
return targets
def OnSecuritiesChanged(self, algorithm, changes):
'''
Description:
Event fired each time the we add/remove securities from the data feed
Args:
algorithm: The algorithm instance that experienced the change in securities
changes: The security additions and removals from the algorithm
'''
newRemovedSymbols = [x.Symbol for x in changes.RemovedSecurities if x.Symbol not in self.removedSymbols]
# get removed symbol and invalidate them in the insight collection
self.removedSymbols.extend(newRemovedSymbols)
self.insightCollection.Clear(self.removedSymbols)
removedList = [x.Value for x in self.removedSymbols]
algorithm.Log('(Portfolio module) securities removed from Universe: ' + str(removedList))
- FactorModelUniverseSelection.py
# region imports
from AlgorithmImports import *
# endregion
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Algorithm.Framework")
from QuantConnect.Data.UniverseSelection import *
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
from Helpers.HelperFunctions import GetFundamentalDataDict, MakeCalculations, GetLongShortLists, UpdatePlots
import pandas as pd
import numpy as np
class FactorModelUniverseSelectionModel(FundamentalUniverseSelectionModel):
def __init__(self,
benchmark = 'STK000000',
nStocks = 500,
lookback = 252,
maxNumberOfPositions = 20,
rebalancingFunc = Expiry.EndOfMonth,
filterFineData = True,
universeSettings = None,
securityInitializer = None):
self.benchmark = benchmark
self.nStocks = nStocks
self.lookback = lookback
self.maxNumberOfPositions = maxNumberOfPositions
self.rebalancingFunc = rebalancingFunc
self.nextRebalance = None
self.initBenchmarkPrice = 0
self.portfolioValueHigh = 0 # initialize portfolioValueHigh for drawdown calculation
self.portfolioValueHighInitialized = False # initialize portfolioValueHighInitialized for drawdown calculation
# super().__init__(filterFineData, universeSettings, securityInitializer)
super().__init__(filterFineData, universeSettings)
def SelectCoarse(self, algorithm, coarse):
''' Perform Universe selection based on price and volume '''
# update plots -----------------------------------------------------------------------------------------------
UpdatePlots(self, algorithm)
# rebalancing logic -------------------------------------------------------------------------------------------
if self.nextRebalance is not None and algorithm.Time < self.nextRebalance:
return Universe.Unchanged
self.nextRebalance = self.rebalancingFunc(algorithm.Time)
# get new coarse candidates -----------------------------------------------------------------------------------
# filtered by price and select the top dollar volume stocks
filteredCoarse = [x for x in coarse if x.HasFundamentalData]
sortedDollarVolume = sorted(filteredCoarse, key = lambda x: x.DollarVolume, reverse = True)
coarseSymbols = [x.Symbol for x in sortedDollarVolume][:(self.nStocks * 2)]
return coarseSymbols
def SelectFine(self, algorithm, fine):
''' Select securities based on fundamental factor modelling '''
sortedMarketCap = sorted(fine, key = lambda x: x.MarketCap, reverse = True)[:self.nStocks]
# generate dictionary with factors -----------------------------------------------------------------------------
fundamentalDataBySymbolDict = GetFundamentalDataDict(algorithm, sortedMarketCap, module = 'universe')
# make calculations to create long/short lists -----------------------------------------------------------------
fineSymbols = list(fundamentalDataBySymbolDict.keys())
calculations = MakeCalculations(algorithm, fineSymbols, self.lookback, Resolution.Daily, fundamentalDataBySymbolDict)
# get long/short lists of symbols
longs, shorts = GetLongShortLists(self, algorithm, calculations)
finalSymbols = longs + shorts
return finalSymbols
- main.py
# region imports
from AlgorithmImports import *
# endregion
### PRODUCT INFORMATION --------------------------------------------------------------------------------
# Copyright Emilio Freire Bauzano
# Use entirely at your own risk.
# This algorithm contains open source code from other sources and no claim is being made to such code.
# Do not remove this copyright notice.
### ----------------------------------------------------------------------------------------------------
from Universe.FactorModelUniverseSelection import FactorModelUniverseSelectionModel
from Alpha.LongShortAlphaCreation import LongShortAlphaCreationModel
from Portfolio.CustomEqualWeightingPortfolioConstruction import CustomEqualWeightingPortfolioConstructionModel
class LongShortEquityFrameworkAlgorithm(QCAlgorithmFramework):
'''
Trading Logic:
Long-Short Equity Strategy using factor modelling
Modules:
Universe:
- Final selection based on factor modelling:
Combination of technical and fundamental factors
- Long the Top N stocks
- Short the Bottom N stocks
Alpha: Creation of Up/Down Insights at the Market Open:
- Up Insights (to go Long)
- Down Insights (to go Short)
Portfolio:
Equal-Weighting Portfolio with monthly rebalancing
Execution:
Immediate Execution with Market Orders
Risk:
Null
'''
def Initialize(self):
### user-defined inputs ---------------------------------------------------------------------------
self.SetStartDate(2018, 1, 1) # set start date
self.SetEndDate(2020, 10, 1) # set end date
self.SetCash(1000000) # set strategy cash
# select benchmark ticker
benchmark = 'STK000000'
# date rule for rebalancing our portfolio by updating long-short positions based on factor values
rebalancingFunc = Expiry.EndOfMonth
# number of stocks to keep for factor modelling calculations
nStocks = 100
# number of positions to hold on each side (long/short)
positionsOnEachSide = 20
# lookback for historical data to calculate factors
lookback = 252
# select the leverage factor
leverageFactor = 1
### --------------------------------------------------------------------------------------------------
# calculate initialAllocationPerSecurity and maxNumberOfPositions
initialAllocationPerSecurity = (1 / positionsOnEachSide) * leverageFactor
maxNumberOfPositions = positionsOnEachSide * 2
# set requested data resolution
self.UniverseSettings.Resolution = Resolution.Hour
# add leverage to new securities (this does not add leverage to current holdings in the account)
leverageNeeded = max(1, maxNumberOfPositions * initialAllocationPerSecurity * leverageFactor)
self.UniverseSettings.Leverage = leverageNeeded + 1
# let's plot the series of daily total portfolio exposure %
portfolioExposurePlot = Chart('Chart Total Portfolio Exposure %')
portfolioExposurePlot.AddSeries(Series('Daily Portfolio Exposure %', SeriesType.Line, ''))
self.AddChart(portfolioExposurePlot)
# let's plot the series of daily number of open longs and shorts
nLongShortPlot = Chart('Chart Number Of Longs/Shorts')
nLongShortPlot.AddSeries(Series('Daily N Longs', SeriesType.Line, ''))
nLongShortPlot.AddSeries(Series('Daily N Shorts', SeriesType.Line, ''))
self.AddChart(nLongShortPlot)
# let's plot the series of drawdown % from the most recent high
drawdownPlot = Chart('Chart Drawdown %')
drawdownPlot.AddSeries(Series('Drawdown %', SeriesType.Line, '%'))
self.AddChart(drawdownPlot)
# add benchmark
self.SetBenchmark(benchmark)
# select modules
self.SetUniverseSelection(FactorModelUniverseSelectionModel(benchmark = benchmark,
nStocks = nStocks,
lookback = lookback,
maxNumberOfPositions = maxNumberOfPositions,
rebalancingFunc = rebalancingFunc))
self.SetAlpha(LongShortAlphaCreationModel(maxNumberOfPositions = maxNumberOfPositions, lookback = lookback))
self.SetPortfolioConstruction(CustomEqualWeightingPortfolioConstructionModel(initialAllocationPerSecurity = initialAllocationPerSecurity,
rebalancingFunc = rebalancingFunc))
self.SetExecution(ImmediateExecutionModel())
self.SetRiskManagement(NullRiskManagementModel())
- ResearchFactorAnalysis.py
# region imports
from AlgorithmImports import *
# endregion
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import scipy.stats as stats
import pandas as pd
import numpy as np
import seaborn as sns
sns.set_style('darkgrid')
pd.plotting.register_matplotlib_converters()
from datetime import timedelta
class FactorAnalysis:
def __init__(self, qb, tickers, startDate, endDate, resolution):
# add symbols
symbols = [qb.AddEquity(ticker, resolution).Symbol for ticker in tickers]
# get historical data at initialization ----------------------------------------------------------
ohlcvDf = qb.History(symbols, startDate, endDate, resolution)
# when using daily resolution, QuantConnect uses the date at midnight after the trading day
# hence skipping Mondays and showing Saturdays. We avoid this by subtracting one day from the index
ohlcvDf.index = ohlcvDf.index.set_levels(ohlcvDf.index.levels[1] - timedelta(1), level = 'time')
self.ohlcvDf = ohlcvDf.dropna()
def GetFactorsDf(self, fct = None):
'''
Description:
Apply a function to a MultiIndex Dataframe of historical data
Group on symbol first to get a ohlcv series per symbol, and apply a custom function to it
in order to get a factor value per symbol and day
Args:
fct: Function to calculate the custom factor
Returns:
MultiIndex Dataframe (symbol/time indexes) with the factor values
'''
if fct is None:
raise ValueError('fct arguments needs to be provided to calculate factors')
# group by symbol to get a timeseries of historical data per symbol and apply CustomFactor function
factorsDf = self.ohlcvDf.groupby('symbol', group_keys = False).apply(lambda x: fct(x)).dropna()
factorsDf.columns = ['Factor_' + str(i + 1) for i in range(len(factorsDf.columns))]
# sort indexes
factorsDf = factorsDf.sort_index(level = ['symbol', 'time'])
return factorsDf
def GetStandardizedFactorsDf(self, factorsDf):
'''
Description:
Winsorize and standardize factors
Args:
factorsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values
Returns:
MultiIndex Dataframe (symbol/time indexes) with standardized factor values
'''
# winsorization
winsorizedFactorsDf = factorsDf.apply(stats.mstats.winsorize, limits = [0.025, 0.025])
# zscore standardization
standardizedFactorsDf = winsorizedFactorsDf.apply(stats.zscore)
return standardizedFactorsDf
def GetCombinedFactorsDf(self, factorsDf, combinedFactorWeightsDict = None):
'''
Description:
Create a combined factor as a linear combination of individual factors
Args:
factorsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values
combinedFactorWeightsDict: Dictionary with factor names and weights to calculate a combined factor
Returns:
MultiIndex Dataframe (symbol/time indexes) with the individual factors and the combined factor
'''
# make a deep copy of the DataFrame
combinedFactorsDf = factorsDf.copy(deep = True)
# calculate a combined factor
if combinedFactorWeightsDict is None:
return combinedFactorsDf
elif not combinedFactorWeightsDict:
combinedFactorsDf['Combined_Factor'] = combinedFactorsDf.sum(axis = 1)
else:
combinedFactorsDf['Combined_Factor'] = sum(combinedFactorsDf[key] * value
for key, value in combinedFactorWeightsDict.items())
return combinedFactorsDf
def GetFinalFactorsDf(self, fct = None, combinedFactorWeightsDict = None, standardize = True):
'''
Description:
- Apply a function to a MultiIndex Dataframe of historical data
Group on symbol first to get a ohlcv series per symbol, and apply a custom function to it
in order to get a factor value per symbol and day
- If required, standardize the factors and remove potential outliers
- If required, add a combined factor as a linear combination of individual factors
Args:
fct: Function to calculate the custom factor
standardize: Boolean to standardize data
combinedFactorWeightsDict: Dictionary with factor names and weights to calculate a combined factor
Returns:
MultiIndex Dataframe (symbol/time indexes) with the factor values
'''
# get factorsDf
factorsDf = self.GetFactorsDf(fct)
# standardize
if standardize:
factorsDf = self.GetStandardizedFactorsDf(factorsDf)
# add combined factor
if combinedFactorWeightsDict is not None:
factorsDf = self.GetCombinedFactorsDf(factorsDf, combinedFactorWeightsDict)
return factorsDf
def GetPricesDf(self, field = 'close'):
'''
Description:
Get a MultiIndex Dataframe of chosen field
Args:
field: open, high, low, close or volume
Returns:
MultiIndex Dataframe (symbol/time indexes) with the chosen field
'''
# select only chose field and turn into a dataframe
pricesDf = self.ohlcvDf[field].to_frame()
pricesDf.columns = ['price']
# forward fill nas and after that drop rows with some nas left
pricesDf = pricesDf.sort_index(level = ['symbol', 'time'])
pricesDf = pricesDf.groupby('symbol').fillna(method = 'ffill').dropna()
return pricesDf
def GetFactorsPricesDf(self, factorsDf, field = 'close'):
'''
Description:
Get a MultiIndex Dataframe (symbol/time indexes) with all the factors and chosen prices
Args:
factorsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values
field: open, high, low, close or volume
Returns:
MultiIndex Dataframe (symbol/time indexes) with all the factors and chosen prices
'''
# get the pricesDf
pricesDf = self.GetPricesDf(field)
# merge factorsDf and pricesDf and fill forward nans by symbol
factorsPricesDf = pd.merge(factorsDf, pricesDf, how = 'right', left_index = True, right_index = True)
factorsPricesDf = factorsPricesDf.sort_index(level = ['symbol', 'time'])
factorsPricesDf = factorsPricesDf.groupby('symbol').fillna(method = 'ffill').dropna()
return factorsPricesDf
def GetFactorsForwardReturnsDf(self, factorsPricesDf, forwardPeriods = [1, 5, 21]):
'''
Description:
Generate a MultiIndex Dataframe (symbol/time indexes) with all previous info plus forward returns
Args:
factorsPricesDf: MultiIndex Dataframe (symbol/time indexes) with all the factors and chosen prices
forwardPeriods: List of integers defining the different periods for forward returns
Returns:
MultiIndex Dataframe (symbol/time indexes) with the factor values and forward returns
'''
# make sure 1 day forward returns are calculated even if not provided by user
if 1 not in forwardPeriods:
forwardPeriods.append(1)
# calculate forward returns per period
for period in forwardPeriods:
factorsPricesDf[str(period) + 'D'] = (factorsPricesDf.groupby('symbol', group_keys = False)
.apply(lambda x: x['price'].pct_change(period).shift(-period)))
# drop column price
factorsForwardReturnsDf = factorsPricesDf.dropna().drop('price', axis = 1)
return factorsForwardReturnsDf
def GetFactorQuantilesForwardReturnsDf(self, factorsDf, field = 'close',
forwardPeriods = [1, 5, 21],
factor = 'Factor_1', q = 5):
'''
Description:
Create a MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
Args:
factorsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values
field: open, high, low, close or volume
forwardPeriods: List of integers defining the different periods for forward returns
factor: Chosen factor to create quantiles for
q: Number of quantile groups
Returns:
MultiIndex Dataframe (symbol/time indexes) with the factor values, forward returns and the quantile groups
'''
# get factorsForwardReturnsDf
factorsPricesDf = self.GetFactorsPricesDf(factorsDf, field)
factorsForwardReturnsDf = self.GetFactorsForwardReturnsDf(factorsPricesDf, forwardPeriods)
# reorder index levels to have time and then symbols so we can then create quantiles per day
factorsForwardReturnsDf = factorsForwardReturnsDf.reorder_levels(['time', 'symbol'])
factorsForwardReturnsDf = factorsForwardReturnsDf.sort_index(level = ['time', 'symbol'])
# calculate quintiles given the chosen factor and rename columns
factorsForwardReturnsDf['Quantile'] = factorsForwardReturnsDf[factor].groupby('time').apply(lambda x: pd.qcut(x, q, labels = False, duplicates = 'drop')).add(1)
factorsForwardReturnsDf['Quantile'] = 'Group_' + factorsForwardReturnsDf['Quantile'].astype(str)
# remove the other factor columns
factorCols = [x for x in factorsForwardReturnsDf.columns if 'Factor' not in x or x == factor]
factorQuantilesForwardReturnsDf = factorsForwardReturnsDf[factorCols]
return factorQuantilesForwardReturnsDf
def GetReturnsByQuantileDf(self, factorQuantilesForwardReturnsDf, forwardPeriod = 1, weighting = 'mean'):
'''
Description:
Generate a SingleIndex Dataframe with period forward returns by quantile and time
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
forwardPeriod: The period of forward returns
weighting: The weighting to apply to the returns in each quantile after grouping:
- mean: Take the average of all the stock returns within each quantile
- factor: Take a factor-weighted return within each quantile
Returns:
SingleIndex Dataframe with period forward returns by quantile and time
'''
# we drop the symbols and convert to a MultiIndex Dataframe with Quantile and time as indexes and forward returns
df = factorQuantilesForwardReturnsDf.droplevel(['symbol'])
df.set_index('Quantile', append = True, inplace = True)
df = df.reorder_levels(['Quantile', 'time'])
df = df.sort_index(level = ['Quantile', 'time'])
# get the column name for the factor and period
factorCol = [x for x in df.columns if 'Factor' in x][0]
periodCol = [str(forwardPeriod) + 'D'][0]
if weighting == 'mean':
df = df[[periodCol]]
# group by Quantile and time and get the mean returns (equal weight across all stocks within each quantiles)
returnsByQuantileDf = df.groupby(['Quantile', 'time']).mean()
elif weighting == 'factor':
relevantCols = [factorCol, periodCol]
df = df[relevantCols]
# group by Quantile and time and create a column with weights based on factor values
df['Factor_Weights'] = (df.groupby(['Quantile', 'time'], group_keys = False)
.apply(lambda x: x[factorCol].abs() / x[factorCol].abs().sum()))
# group by Quantile and time and calculate the factor weighted average returns
returnsByQuantileDf = (df.groupby(['Quantile', 'time'], group_keys = False)
.apply(lambda x: (x['Factor_Weights'] * x[periodCol]).sum())).to_frame()
# unstack to convert to SingleIndex Dataframe
returnsByQuantileDf = returnsByQuantileDf.unstack(0).fillna(0)
returnsByQuantileDf.columns = returnsByQuantileDf.columns.droplevel(0)
returnsByQuantileDf.columns.name = None
# finally keep every nth row to match with the forward period returns
returnsByQuantileDf = returnsByQuantileDf.iloc[::forwardPeriod, :]
return returnsByQuantileDf
def GetMeanReturnsByQuantileDf(self, factorQuantilesForwardReturnsDf):
'''
Description:
Generate a SingleIndex Dataframe with mean returns by quantile and time
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
Returns:
SingleIndex Dataframe with mean returns by quantile and time
'''
# remove factor columns, group by quantile and take the average return
factorCol = [x for x in factorQuantilesForwardReturnsDf.columns if 'Factor' in x]
quantileMeanReturn = factorQuantilesForwardReturnsDf.drop(factorCol, axis = 1).groupby('Quantile').mean()
return quantileMeanReturn
def GetPortfolioLongShortReturnsDf(self, returnsByQuantileDf, portfolioWeightsDict = None):
'''
Description:
Generate a SingleIndex Dataframe with the returns of a Long-Short portfolio
Args:
returnsByQuantileDf: SingleIndex Dataframe with period forward returns by quantile and time
portfolioWeightsDict: Dictionary with quantiles and weights to create a portfolio of returns
Returns:
SingleIndex Dataframe with the returns of Long-Short portfolio
'''
# if no portfolioWeightsDict are provided, create a default one
# going 100% long top quintile and 100% short bottom quintile
if portfolioWeightsDict is None:
quantileGroups = sorted(list(returnsByQuantileDf.columns))
topQuantile = quantileGroups[-1]
bottomQuantile = quantileGroups[0]
portfolioWeightsDict = {topQuantile: 1, bottomQuantile: -1}
# we calculate the weighted average portfolio returns based on given weights for each quintile
col = list(portfolioWeightsDict.keys())
portfolioLongShortReturnsDf = returnsByQuantileDf.loc[: , col]
portfolioLongShortReturnsDf[col[0]] = portfolioLongShortReturnsDf[col[0]] * portfolioWeightsDict[col[0]]
portfolioLongShortReturnsDf[col[1]] = portfolioLongShortReturnsDf[col[1]] * portfolioWeightsDict[col[1]]
portfolioLongShortReturnsDf['Strategy'] = portfolioLongShortReturnsDf.sum(axis = 1)
portfolioLongShortReturnsDf = portfolioLongShortReturnsDf[['Strategy']]
return portfolioLongShortReturnsDf
def GetCumulativeReturnsDf(self, returnsDf):
'''
Description:
Convert a DataFrame of returns into a DataFrame of cumulative returns
Args:
returnsDf: SingleIndex Dataframe with returns
Returns:
SingleIndex Dataframe with cumulative returns
'''
cumulativeReturnsDf = returnsDf.add(1).cumprod().add(-1)
return cumulativeReturnsDf
# ploting functions -----------------------------------------------------------------------------------------
def PlotFactorsCorrMatrix(self, factorsDf):
'''
Description:
Plot the factors correlation matrix
Args:
factorsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values
Returns:
Plot the factors correlation matrix
'''
corrMatrix = round(factorsDf.corr(), 2)
nCol = len(list(factorsDf.columns))
plt.subplots(figsize = (nCol, nCol))
sns.heatmap(corrMatrix, annot = True)
plt.show()
def PlotHistograms(self, factorsDf):
'''
Description:
Plot the histogram for each factor
Args:
factorsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values
Returns:
Plot the histogram for each factor
'''
nCol = len(list(factorsDf.columns))
factorsDf.hist(figsize = (nCol * 3, nCol * 2), bins = 50)
plt.show()
def PlotBoxPlotQuantilesCount(self, factorQuantilesForwardReturnsDf):
'''
Description:
Plot a box plot with the distributions of number of stocks in each quintile.
The objective is to make sure each quintile has an almost equal number of stocks most of the time
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
Returns:
Plot a box plot with the distributions of number of stocks in each quintile
'''
factorCol = [x for x in factorQuantilesForwardReturnsDf.columns if 'Factor' in x]
df = factorQuantilesForwardReturnsDf.groupby(['Quantile', 'time'])[factorCol].count()
df = df.unstack(0)
df.columns = df.columns.droplevel(0)
df.name = None
ax = sns.boxplot(data = df, width = 0.5, palette = "colorblind", orient = 'h')
ax.set_title('Distribution Of Number Of Assets Within Quintiles')
plt.show()
def PlotMeanReturnsByQuantile(self, factorQuantilesForwardReturnsDf):
'''
Description:
Plot the mean return for each quantile group and forward return period
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
Returns:
Plot with the mean return for each quantile group and forward return period
'''
meanReturnsByQuantileDf = self.GetMeanReturnsByQuantileDf(factorQuantilesForwardReturnsDf)
# plot
ax = meanReturnsByQuantileDf.plot(kind = 'bar', figsize = (12, 5))
ax.set_title('Mean Returns By Quantile Group And Forward Period Return', fontdict = {'fontsize': 15})
ax.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
plt.show()
def PlotCumulativeReturnsByQuantile(self, factorQuantilesForwardReturnsDf,
forwardPeriod = 1, weighting = 'mean'):
'''
Description:
Plot cumulative returns per quantile group
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
forwardPeriod: The period of forward returns
weighting: The weighting to apply to the returns in each quantile after grouping:
- mean: Take the average of all the stock returns within each quantile
- factor: Take a factor-weighted return within each quantile
Returns:
Plot with the cumulative returns per quantile group
'''
# get returns by quantile
returnsByQuantileDf = self.GetReturnsByQuantileDf(factorQuantilesForwardReturnsDf, forwardPeriod, weighting)
cumulativeReturnsByQuantileDf = self.GetCumulativeReturnsDf(returnsByQuantileDf)
# take logarithm for better visualization
cumulativeReturnsByQuantileDf = np.log(1 + cumulativeReturnsByQuantileDf)
# get the relevant columns
colTop = cumulativeReturnsByQuantileDf.iloc[:, [-1]].columns[0]
colBottom = cumulativeReturnsByQuantileDf.iloc[:, [0]].columns[0]
colMiddle = cumulativeReturnsByQuantileDf.drop([colTop, colBottom], axis = 1).columns
# plot
fig, ax = plt.subplots(figsize = (12, 5))
ax.plot(cumulativeReturnsByQuantileDf[colBottom], color = 'red', linewidth = 2)
ax.plot(cumulativeReturnsByQuantileDf[colMiddle], alpha = 0.3)
ax.plot(cumulativeReturnsByQuantileDf[colTop], color = 'green', linewidth = 2)
# formatting
ax.axhline(y = 0, color = 'black', linestyle = '--', linewidth = 0.5)
ax.set_title('Cumulative Log-Returns By Quantile Group', fontdict = {'fontsize': 15})
ax.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
ax.legend(cumulativeReturnsByQuantileDf.columns, loc = 'best')
plt.show()
def PlotPortfolioLongShortCumulativeReturns(self, factorQuantilesForwardReturnsDf,
forwardPeriod = 1, weighting = 'mean',
portfolioWeightsDict = None):
'''
Description:
Plot cumulative returns for a long-short portfolio
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
forwardPeriod: The period of forward returns
weighting: The weighting to apply to the returns in each quantile after grouping:
- mean: Take the average of all the stock returns within each quantile
- factor: Take a factor-weighted return within each quantile
Returns:
Plot cumulative returns for a long-short portfolio
'''
# get returns by quantile
returnsByQuantileDf = self.GetReturnsByQuantileDf(factorQuantilesForwardReturnsDf, forwardPeriod, weighting)
# calculate returns for a long-short portolio
portfolioLongShortReturnsDf = self.GetPortfolioLongShortReturnsDf(returnsByQuantileDf, portfolioWeightsDict)
portfolioLongShortCumulativeReturnsDf = self.GetCumulativeReturnsDf(portfolioLongShortReturnsDf)
# prepare plot
fig, ax = plt.subplots(figsize = (12, 5))
# plot portfolio
colPortfolio = portfolioLongShortCumulativeReturnsDf.iloc[:, [0]].columns[0]
ax.plot(portfolioLongShortCumulativeReturnsDf[colPortfolio], color = 'black', linewidth = 2)
if len(portfolioLongShortCumulativeReturnsDf.columns) > 1:
colFactors = portfolioLongShortCumulativeReturnsDf.iloc[:, 1:].columns
# plot factors
ax.plot(portfolioLongShortCumulativeReturnsDf[colFactors], alpha = 0.3)
# formatting
ax.axhline(y = 0, color = 'black', linestyle = '--', linewidth = 0.5)
ax.set_title('Cumulative Returns Long-Short Portfolio', fontdict = {'fontsize': 15})
ax.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
ax.legend(portfolioLongShortCumulativeReturnsDf.columns, loc = 'best')
plt.show()
def PlotIC(self, factorQuantilesForwardReturnsDf):
'''
Description:
Plot the Information Coefficient (Spearman Rank Correlation) for different periods along with a moving average
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
Returns:
Plot of the Information Coefficient (Spearman Rank Correlation) for different periods along with a moving average
'''
# get the forward periods and factor columns
forwardPeriods = [int(x.split('D', 1)[0]) for x in factorQuantilesForwardReturnsDf.columns if 'D' in x]
factorCol = [x for x in factorQuantilesForwardReturnsDf.columns if 'Factor' in x]
# iterate over the periods
for period in forwardPeriods:
col = str(period) + 'D'
# calculate the spearman rank coefficient for each day between the factor values and forward returns
icDf = (factorQuantilesForwardReturnsDf.groupby('time')
.apply(lambda x: stats.spearmanr(x[factorCol], x[col])[0]).to_frame().dropna())
icDf.columns = ['IC']
# apply a moving average for smoothing
icDf['21D Moving Average'] = icDf.rolling(21).apply(lambda x: np.mean(x))
# plot
fig, ax = plt.subplots(figsize = (12, 5))
ax.plot(icDf['IC'], alpha = 0.5)
ax.plot(icDf['21D Moving Average'])
ax.axhline(y = 0, color = 'black', linestyle = '--', linewidth = 0.5)
mu = icDf['IC'].mean()
sigma = icDf['IC'].std()
textstr = '\n'.join((
r'$\mu=%.2f$' % (mu, ),
r'$\sigma=%.2f$' % (sigma, )))
props = dict(boxstyle = 'round', facecolor = 'white', alpha = 0.5)
ax.text(0.05, 0.95, textstr, transform = ax.transAxes, fontsize = 14,
verticalalignment = 'top', bbox = props)
ax.set_title(col + ' Forward Return Information Coefficient (IC)', fontdict = {'fontsize': 15})
ax.legend(icDf.columns, loc = 'upper right')
plt.show()
# run full factor analysis --------------------------------------------------------------------------------------
def RunFactorAnalysis(self, factorQuantilesForwardReturnsDf, forwardPeriod = 1,
weighting = 'mean', portfolioWeightsDict = None, makePlots = True):
'''
Description:
Run all needed functions and generate relevant DataFrames and plots for analysis
Args:
factorQuantilesForwardReturnsDf: MultiIndex Dataframe (symbol/time indexes) with the factor values,
forward returns and the quantile groups
forwardPeriod: The period of forward returns
weighting: The weighting to apply to the returns in each quantile after grouping:
- mean: Take the average of all the stock returns within each quantile
- factor: Take a factor-weighted return within each quantile
portfolioWeightsDict: Dictionary with quantiles and weights to create a portfolio of returns
Returns:
Plots for factor analysis
'''
# plotting
if makePlots:
self.PlotMeanReturnsByQuantile(factorQuantilesForwardReturnsDf)
self.PlotCumulativeReturnsByQuantile(factorQuantilesForwardReturnsDf)
self.PlotPortfolioLongShortCumulativeReturns(factorQuantilesForwardReturnsDf)
self.PlotIC(factorQuantilesForwardReturnsDf)
# keep DataFrames
self.returnsByQuantileDf = self.GetReturnsByQuantileDf(factorQuantilesForwardReturnsDf, forwardPeriod, weighting)
self.cumulativeReturnsByQuantileDf = self.GetCumulativeReturnsDf(self.returnsByQuantileDf)
self.portfolioLongShortReturnsDf = self.GetPortfolioLongShortReturnsDf(self.returnsByQuantileDf, portfolioWeightsDict)
self.portfolioLongShortCumulativeReturnsDf = self.GetCumulativeReturnsDf(self.portfolioLongShortReturnsDf)
- ResearchRiskAnalysis.py
# region imports
from AlgorithmImports import *
# endregion
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import statsmodels.api as sm
import pandas as pd
import numpy as np
import seaborn as sns
sns.set_style('darkgrid')
pd.plotting.register_matplotlib_converters()
from statsmodels.regression.rolling import RollingOLS
from io import StringIO
class RiskAnalysis:
def __init__(self, qb):
# get Fama-French and industry factors
industryFactorsUrl = 'https://www.dropbox.com/s/24bjtztzglo3eyf/12_Industry_Portfolios_Daily.CSV?dl=1'
ffFiveFactorsUrl = 'https://www.dropbox.com/s/88m1nohi597et20/F-F_Research_Data_5_Factors_2x3_daily.CSV?dl=1'
self.industryFactorsDf = self.GetExternalFactorsDf(qb, industryFactorsUrl)
self.ffFiveFactorsDf = self.GetExternalFactorsDf(qb, ffFiveFactorsUrl)
def GetExternalFactorsDf(self, qb, url):
'''
Description:
Download a DataFrame with data from external sources
Args:
qb: QuantBook
url: URL for the data source
Returns:
SingleIndex Dataframe
'''
strFile = qb.Download(url)
df = pd.read_csv(StringIO(strFile), sep = ',')
df['Date'] = pd.to_datetime(df['Date'], format = '%Y%m%d')
df.set_index('Date', inplace = True)
df = df.div(100)
df.drop('RF', axis = 1, errors = 'ignore', inplace = True)
return df
def GetCombinedReturnsDf(self, returnsDf, externalFactorsDf = None):
'''
Description:
Merge two DataFrames
Args:
returnsDf: SingleIndex Dataframe with returns from our strategy
externalFactorsDf: SingleIndex Dataframe with returns from external factors
Returns:
SingleIndex Dataframe with returns
'''
# if no externalFactorsDf is provided, use the default Fama-French Five Factors
if externalFactorsDf is None:
externalFactorsDf = self.ffFiveFactorsDf
# merge returnsDf with externalFactorsDf
combinedReturnsDf = pd.merge(returnsDf, externalFactorsDf, left_index = True, right_index = True)
return combinedReturnsDf
def GetCumulativeReturnsDf(self, returnsDf):
'''
Description:
Convert a DataFrame of returns into a DataFrame of cumulative returns
Args:
returnsDf: SingleIndex Dataframe with returns
Returns:
SingleIndex Dataframe with cumulative returns
'''
cumulativeReturnsDf = returnsDf.add(1).cumprod().add(-1)
return cumulativeReturnsDf
def RunRegression(self, returnsDf, dependentColumn = 'Strategy'):
'''
Description:
Run Regression using the dependentColumn against the rest of the columns
Args:
returnsDf: SingleIndex Dataframe with returns
dependentColumn: Name for the column to be used as dependent variable
Returns:
Summary of the model
'''
# create variables
Y = returnsDf[[dependentColumn]]
X = returnsDf[[x for x in returnsDf.columns if x != dependentColumn]]
# adding a constant
X = sm.add_constant(X)
# fit regression model
model = sm.OLS(Y, X).fit()
# show summary from the model
print(model.summary())
return model
def RunRollingRegression(self, returnsDf, dependentColumn = 'Strategy', lookback = 126):
'''
Description:
Run Rolling Regression using the dependentColumn against the rest of the columns
Args:
returnsDf: SingleIndex Dataframe with returns
dependentColumn: Name for the column to be used as dependent variable
lookback: Number of observations for the lookback window
Returns:
Rolling Regression Model
'''
endog = returnsDf[[dependentColumn]]
exogVariables = [x for x in returnsDf.columns if x != dependentColumn]
exog = sm.add_constant(returnsDf[exogVariables])
rollingModel = RollingOLS(endog, exog, window = lookback).fit()
return rollingModel
# ploting functions -----------------------------------------------------------------------------------------
def PlotCumulativeReturns(self, returnsDf):
'''
Description:
Plot cumulative returns
Args:
returnsDf: SingleIndex Dataframe with returns
Returns:
Plot cumulative returns
'''
# calculate cumulative returns
cumulativeReturnsDf = self.GetCumulativeReturnsDf(returnsDf)
# take logarithm for better visualization
cumulativeReturnsDf = np.log(1 + cumulativeReturnsDf)
# prepare plot
fig, ax = plt.subplots(figsize = (12, 5))
# plot portfolio
colPortfolio = cumulativeReturnsDf.iloc[:, [0]].columns[0]
ax.plot(cumulativeReturnsDf[colPortfolio], color = 'black', linewidth = 2)
if len(cumulativeReturnsDf.columns) > 1:
colFactors = cumulativeReturnsDf.iloc[:, 1:].columns
# plot factors
ax.plot(cumulativeReturnsDf[colFactors], alpha = 0.5)
# formatting
ax.axhline(y = 0, color = 'black', linestyle = '--', linewidth = 0.5)
ax.set_title('Cumulative Log-Returns', fontdict = {'fontsize': 15})
ax.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
ax.legend(cumulativeReturnsDf.columns, loc = 'best')
plt.show()
def PlotRegressionModel(self, returnsDf, dependentColumn = 'Strategy'):
'''
Description:
Run Regression and plot partial regression
Args:
returnsDf: SingleIndex Dataframe with returns
dependentColumn: Name for the column to be used as dependent variable
Returns:
Summary of the regression model and partial regression plots
'''
# run regression
model = self.RunRegression(returnsDf, dependentColumn)
# plot partial regression
exogVariables = [x for x in returnsDf.columns if x != dependentColumn]
figsize = (10, len(exogVariables) * 2)
fig = plt.figure(figsize = figsize)
fig = sm.graphics.plot_partregress_grid(model, fig = fig)
plt.show()
def PlotRollingRegressionCoefficients(self, returnsDf, dependentColumn = 'Strategy', lookback = 126):
'''
Description:
Run Rolling Regression and plot the time series of estimated coefficients for each predictor
Args:
returnsDf: SingleIndex Dataframe with returns
dependentColumn: Name for the column to be used as dependent variable
lookback: Number of observations for the lookback window
Returns:
Plot of time series of estimated coefficients for each predictor
'''
# run rolling regression
rollingModel = self.RunRollingRegression(returnsDf, dependentColumn, lookback)
exogVariables = [x for x in returnsDf.columns if x != dependentColumn]
# plot
figsize = (10, len(exogVariables) * 3)
fig = rollingModel.plot_recursive_coefficient(variables = exogVariables, figsize = figsize)
plt.show()
def PlotBoxPlotRollingFactorExposure(self, returnsDf, dependentColumn = 'Strategy', lookback = 126):
'''
Description:
Run Rolling Regression and make a box plot with the distributions of the estimated coefficients
Args:
returnsDf: SingleIndex Dataframe with returns
dependentColumn: Name for the column to be used as dependent variable
lookback: Number of observations for the lookback window
Returns:
Box plot with distributions of estimated coefficients during the rolling regression
'''
# run rolling regression
rollingModel = self.RunRollingRegression(returnsDf, dependentColumn, lookback)
fig, ax = plt.subplots(figsize = (10, 8))
ax = sns.boxplot(data = rollingModel.params.dropna().drop('const', axis = 1),
width = 0.5,
palette = "colorblind",
orient = 'h')
ax.axvline(x = 0, color = 'black', linestyle = '--', linewidth = 0.5)
ax.set_title('Distribution of Risk Factor Rolling Exposures', fontdict = {'fontsize': 15})
plt.show()
# run full risk analysis --------------------------------------------------------------------------------------
def RunRiskAnalysis(self, returnsDf, externalFactorsDf = None, dependentColumn = 'Strategy', lookback = 126):
# if no externalFactorsDf is provided, use the default Fama-French Five Factors
if externalFactorsDf is None:
externalFactorsDf = self.ffFiveFactorsDf
# merge returnsDf with externalFactorsDf
combinedReturnsDf = pd.merge(returnsDf, externalFactorsDf, left_index = True, right_index = True)
# plot
self.PlotCumulativeReturns(combinedReturnsDf)
print('---------------------------------------------------------------------------------------------')
print('---- Regression Analysis --------------------------------------------------------------------')
print('---------------------------------------------------------------------------------------------')
self.PlotRegressionModel(combinedReturnsDf, dependentColumn)
print('---------------------------------------------------------------------------------------------')
print('---- Rolling Regression Analysis (Rolling Coefficients) -------------------------------------')
print('---------------------------------------------------------------------------------------------')
self.PlotRollingRegressionCoefficients(combinedReturnsDf, dependentColumn, lookback)
self.PlotBoxPlotRollingFactorExposure(combinedReturnsDf, dependentColumn, lookback)
小结
成功运行。
补充:
Anaconda | A Faster Solver for Conda: Libmamba
conda 22.11 update: The libmamba solver's experimental flag has been removed. To use the new solver, update conda in your base environment:
conda update -n base conda
To install and set the new solver, run the following commands:
conda install -n base conda-libmamba-solver
conda config --set solver libmamba
-随机因子值的生成
config.json增加"fundamental-data-provider": “QuantConnect.Data.UniverseSelection.CoarseFundamentalDataProviderExt”,
// defines the 'backtesting' environment
"backtesting": {
"live-mode": false,
"setup-handler": "QuantConnect.Lean.Engine.Setup.BacktestingSetupHandler",
"result-handler": "QuantConnect.Lean.Engine.Results.BacktestingResultHandler",
"data-feed-handler": "QuantConnect.Lean.Engine.DataFeeds.FileSystemDataFeed",
"real-time-handler": "QuantConnect.Lean.Engine.RealTime.BacktestingRealTimeHandler",
"history-provider": [ "QuantConnect.Lean.Engine.HistoricalData.SubscriptionDataReaderHistoryProvider" ],
"fundamental-data-provider": "QuantConnect.Data.UniverseSelection.CoarseFundamentalDataProviderExt",
"transaction-handler": "QuantConnect.Lean.Engine.TransactionHandlers.BacktestingTransactionHandler"
},
复制QuantConnect.Data.UniverseSelection.CoarseFundamentalDataProvider,新建QuantConnect.Data.UniverseSelection.CoarseFundamentalDataProviderExt(实际不必要,使用CoarseFundamentalDataProvider也可以)
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.IO;
using System.Collections.Generic;
using QuantConnect.Data.Fundamental;
using System.Reflection;
using System.Linq;
using Fasterflect;
using QuantConnect.Interfaces;
namespace QuantConnect.Data.UniverseSelection
{
/// <summary>
/// Coarse base fundamental data provider
/// </summary>
public class CoarseFundamentalDataProviderExt : BaseFundamentalDataProvider
{
private DateTime _date;
private readonly Dictionary<SecurityIdentifier, CoarseFundamental> _coarseFundamental = new();
/// <summary>
/// Will fetch the requested fundamental information for the requested time and symbol
/// </summary>
/// <typeparam name="T">The expected data type</typeparam>
/// <param name="time">The time to request this data for</param>
/// <param name="securityIdentifier">The security identifier</param>
/// <param name="name">The name of the fundamental property</param>
/// <returns>The fundamental information</returns>
public override T Get<T>(DateTime time, SecurityIdentifier securityIdentifier, FundamentalProperty name)
{
var enumName = Enum.GetName(name);
lock (_coarseFundamental)
{
if (time == _date)
{
return GetProperty<T>(securityIdentifier, enumName);
}
_date = time;
var path = Path.Combine(Globals.DataFolder, "equity", "usa", "fundamental", "coarse", $"{time:yyyyMMdd}.csv");
var fileStream = DataProvider.Fetch(path);
if (fileStream == null)
{
return GetDefault<T>();
}
_coarseFundamental.Clear();
using (var reader = new StreamReader(fileStream))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var coarse = Read(line, time);
if (coarse != null)
{
_coarseFundamental[coarse.Symbol.ID] = coarse;
}
}
}
return GetProperty<T>(securityIdentifier, enumName);
}
}
/// <summary>
/// Reads the given line and returns a CoarseFundamentalSource with the information within it
/// </summary>
public static FineFundamentalSource Read(string line, DateTime date)
{
try
{
var csv = line.Split(',');
var coarse = new FineFundamentalSource
{
Symbol = new Symbol(SecurityIdentifier.Parse(csv[0]), csv[1]),
Time = date,
Value = csv[2].ToDecimal(),
VolumeSetter = csv[3].ToInt64(),
DollarVolumeSetter = (double)csv[4].ToDecimal()
};
if (csv.Length > 5)
{
coarse.HasFundamentalDataSetter = csv[5].ConvertInvariant<bool>();
}
if (csv.Length > 7)
{
coarse.PriceFactorSetter = csv[6].ToDecimal();
coarse.SplitFactorSetter = csv[7].ToDecimal();
}
//if (csv.Length > 8)
//{
// Type type = typeof(ValuationRatiosExt);
// PropertyInfo[] propertyInfos = type.GetProperties().Where(p => p.PropertyType == typeof(double)).ToArray();
// for (int i = 8, j = 0; (i < csv.Length) && (j < propertyInfos.Length); i++, j++)
// {
// coarse.ValuationRatios.SetPropertyValue(propertyInfos[j].Name, double.Parse(csv[i]));
// }
//}
return coarse;
}
catch (Exception ex)
{
var msg = ex.Message;
return null;
}
}
private dynamic GetProperty<T>(SecurityIdentifier securityIdentifier, string property)
{
if (!_coarseFundamental.TryGetValue(securityIdentifier, out var coarse))
{
return GetDefault<T>();
}
switch (property)
{
case nameof(CoarseFundamental.Price):
return coarse.Price;
case nameof(CoarseFundamental.Value):
return coarse.Value;
case nameof(CoarseFundamental.Market):
return coarse.Market;
case nameof(CoarseFundamental.Volume):
return coarse.Volume;
case nameof(CoarseFundamental.PriceFactor):
return coarse.PriceFactor;
case nameof(CoarseFundamental.SplitFactor):
return coarse.SplitFactor;
case nameof(CoarseFundamental.DollarVolume):
return coarse.DollarVolume;
case nameof(CoarseFundamental.HasFundamentalData):
//return false;
return coarse.HasFundamentalData;
}
return GetDefault<T>();
}
/// <summary>
/// Coarse fundamental with setters
/// </summary>
public class FineFundamentalSource : FineFundamental
{
/// <summary>
/// Property to set the volume of the Coarse Fundamental
/// </summary>
public long VolumeSetter { get; init; }
/// <summary>
/// Property to set the dollar volume of the Coarse Fundamental
/// </summary>
public double DollarVolumeSetter { get; init; }
/// <summary>
/// Property to set the price factor of the Coarse Fundamental
/// </summary>
public decimal PriceFactorSetter { get; set; } = 1;
/// <summary>
/// Property to set the split factor of the Coarse Fundamental
/// </summary>
public decimal SplitFactorSetter { get; set; } = 1;
/// <summary>
/// Property to indicate if the Coarse Fundamental has fundamental data
/// </summary>
public bool HasFundamentalDataSetter { get; set; }
/// <summary>
/// Gets the day's dollar volume for this symbol
/// </summary>
public override double DollarVolume => DollarVolumeSetter;
/// <summary>
/// Gets the day's total volume
/// </summary>
public override long Volume => VolumeSetter;
/// <summary>
/// Returns whether the symbol has fundamental data for the given date
/// </summary>
public override bool HasFundamentalData => HasFundamentalDataSetter;
/// <summary>
/// Gets the price factor for the given date
/// </summary>
public override decimal PriceFactor => PriceFactorSetter;
/// <summary>
/// Gets the split factor for the given date
/// </summary>
public override decimal SplitFactor => SplitFactorSetter;
}
}
}
同样复制CoarseFundamental.cs到CoarseFundamentalExt.cs,添加ToRowExt函数,作用是根据ValuationRatios属性添加因子值,其他基本面数据添加因子值可依此参考
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Linq;
using System.Globalization;
using QuantConnect.Data.Fundamental;
using System.Reflection;
namespace QuantConnect.Data.UniverseSelection
{
/// <summary>
/// Defines summary information about a single symbol for a given date
/// </summary>
public class CoarseFundamentalExt : BaseData
{
/// <summary>
/// Gets the market for this symbol
/// </summary>
public string Market => Symbol.ID.Market;
/// <summary>
/// Gets the day's dollar volume for this symbol
/// </summary>
public virtual double DollarVolume { get; }
/// <summary>
/// Gets the day's total volume
/// </summary>
public virtual long Volume { get; }
/// <summary>
/// Returns whether the symbol has fundamental data for the given date
/// </summary>
public virtual bool HasFundamentalData { get; }
/// <summary>
/// Gets the price factor for the given date
/// </summary>
public virtual decimal PriceFactor { get; } = 1;
/// <summary>
/// Gets the split factor for the given date
/// </summary>
public virtual decimal SplitFactor { get; } = 1;
/// <summary>
/// Gets the combined factor used to create adjusted prices from raw prices
/// </summary>
public decimal PriceScaleFactor => PriceFactor * SplitFactor;
/// <summary>
/// Gets the split and dividend adjusted price
/// </summary>
public decimal AdjustedPrice => Price * PriceScaleFactor;
/// <summary>
/// The end time of this data.
/// </summary>
public override DateTime EndTime
{
get { return Time + QuantConnect.Time.OneDay; }
set { Time = value - QuantConnect.Time.OneDay; }
}
/// <summary>
/// Gets the raw price
/// </summary>
public override decimal Price => Value;
/// <summary>
/// Initializes a new instance of the <see cref="CoarseFundamental"/> class
/// </summary>
public CoarseFundamentalExt()
{
}
/// <summary>
/// Return the URL string source of the file. This will be converted to a stream
/// </summary>
/// <param name="config">Configuration object</param>
/// <param name="date">Date of this source file</param>
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
/// <returns>String URL of source file.</returns>
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
{
throw new InvalidOperationException($"Coarse type is obsolete, please use {nameof(Fundamental)}");
}
/// <summary>
/// Reader converts each line of the data source into BaseData objects. Each data type creates its own factory method, and returns a new instance of the object
/// each time it is called.
/// </summary>
/// <param name="config">Subscription data config setup object</param>
/// <param name="line">Line of the source document</param>
/// <param name="date">Date of the requested data</param>
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
/// <returns>Instance of the T:BaseData object generated by this line of the CSV</returns>
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
{
throw new InvalidOperationException($"Coarse type is obsolete, please use {nameof(Fundamental)}");
}
/// <summary>
/// Converts a given fundamental data point into row format
/// </summary>
public static string ToRow(CoarseFundamental coarse)
{
// sid,symbol,close,volume,dollar volume,has fundamental data,price factor,split factor
var values = new object[]
{
coarse.Symbol.ID,
coarse.Symbol.Value,
coarse.Value,
coarse.Volume,
coarse.DollarVolume,
coarse.HasFundamentalData,
coarse.PriceFactor,
coarse.SplitFactor
};
return string.Join(",", values.Select(s => Convert.ToString(s, CultureInfo.InvariantCulture)));
}
/// <summary>
///
/// </summary>
public static string ToRowExt(CoarseFundamental coarse)
{
// sid,symbol,close,volume,dollar volume,has fundamental data,price factor,split factor
var values = new object[]
{
coarse.Symbol.ID,
coarse.Symbol.Value,
coarse.Value,
coarse.Volume,
coarse.DollarVolume,
coarse.HasFundamentalData,
coarse.PriceFactor,
coarse.SplitFactor
};
Type type = typeof(ValuationRatiosExt);
PropertyInfo[] propertyInfos = type.GetProperties().Where(p => p.PropertyType == typeof(double)).ToArray();
int length = propertyInfos.Length;
object[] fundamentalProperties = new object[length];
for (int i = 0; i < length; i++)
{
fundamentalProperties[i] = new Random().NextDouble();
}
var data = new object[values.Length+fundamentalProperties.Length];
Array.Copy(values, data, values.Length);
Array.Copy(fundamentalProperties, 0, data, values.Length, fundamentalProperties.Length);
return string.Join(",", data.Select(s => Convert.ToString(s, CultureInfo.InvariantCulture)));
}
}
}
复制ValuationRatios.cs到ValuationRatiosExt.cs,然后两个文件都进行属性修改,由只读变为读写
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2023 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Linq;
using Python.Runtime;
using Newtonsoft.Json;
using System.Collections.Generic;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Data.Fundamental
{
/// <summary>
/// Definition of the ValuationRatios class
/// </summary>
public class ValuationRatios : FundamentalTimeDependentProperty
{
/// <summary>
/// Dividend per share / Diluted earnings per share
/// </summary>
/// <remarks>
/// Morningstar DataId: 14000
/// </remarks>
[JsonProperty("14000")]
public double PayoutRatio { get; set; }
/// <summary>
/// ROE * (1 - Payout Ratio)
/// </summary>
/// <remarks>
/// Morningstar DataId: 14001
/// </remarks>
[JsonProperty("14001")]
public double SustainableGrowthRate { get; set; }
/// <summary>
/// Refers to the ratio of free cash flow to enterprise value. Morningstar calculates the ratio by using the underlying data reported in the company filings or reports: FCF /Enterprise Value.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14002
/// </remarks>
[JsonProperty("14002")]
public double CashReturn { get; set; }
/// <summary>
/// Sales / Average Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14003
/// </remarks>
[JsonProperty("14003")]
public double SalesPerShare { get; set; }
/// <summary>
/// Common Shareholder's Equity / Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14004
/// </remarks>
[JsonProperty("14004")]
public double BookValuePerShare { get; set; }
/// <summary>
/// Cash Flow from Operations / Average Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14005
/// </remarks>
[JsonProperty("14005")]
public double CFOPerShare { get; set; }
/// <summary>
/// Free Cash Flow / Average Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14006
/// </remarks>
[JsonProperty("14006")]
public double FCFPerShare { get; set; }
/// <summary>
/// Diluted EPS / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14007
/// </remarks>
[JsonProperty("14007")]
public double EarningYield { get; set; }
/// <summary>
/// Adjusted Close Price/ EPS. If the result is negative, zero, >10,000 or <0.001, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14008
/// </remarks>
[JsonProperty("14008")]
public double PERatio { get; set; }
/// <summary>
/// SalesPerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14009
/// </remarks>
[JsonProperty("14009")]
public double SalesYield { get; set; }
/// <summary>
/// Adjusted close price / Sales Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14010
/// </remarks>
[JsonProperty("14010")]
public double PSRatio { get; set; }
/// <summary>
/// BookValuePerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14011
/// </remarks>
[JsonProperty("14011")]
public double BookValueYield { get; set; }
/// <summary>
/// Adjusted close price / Book Value Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14012
/// </remarks>
[JsonProperty("14012")]
public double PBRatio { get; set; }
/// <summary>
/// CFOPerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14013
/// </remarks>
[JsonProperty("14013")]
public double CFYield { get; set; }
/// <summary>
/// Adjusted close price /Cash Flow Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14014
/// </remarks>
[JsonProperty("14014")]
public double PCFRatio { get; set; }
/// <summary>
/// FCFPerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14015
/// </remarks>
[JsonProperty("14015")]
public double FCFYield { get; set; }
/// <summary>
/// Adjusted close price/ Free Cash Flow Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14016
/// </remarks>
[JsonProperty("14016")]
public double FCFRatio { get; set; }
/// <summary>
/// Dividends Per Share over the trailing 12 months / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14017
/// </remarks>
[JsonProperty("14017")]
public double TrailingDividendYield { get; set; }
/// <summary>
/// (Current Dividend Per Share * Payout Frequency) / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14018
/// </remarks>
[JsonProperty("14018")]
public double ForwardDividendYield { get; set; }
/// <summary>
/// Estimated Earnings Per Share / Price Note: a) The "Next" Year's EPS Estimate is used; For instance, if today's actual date is March 1, 2009, the "Current" EPS Estimate for MSFT is June 2009, and the "Next" EPS Estimate for MSFT is June 2010; the latter is used. b) The eps estimated data is sourced from a third party.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14019
/// </remarks>
[JsonProperty("14019")]
public double ForwardEarningYield { get; set; }
/// <summary>
/// 1 / ForwardEarningYield If result is negative, then null
/// </summary>
/// <remarks>
/// Morningstar DataId: 14020
/// </remarks>
[JsonProperty("14020")]
public double ForwardPERatio { get; set; }
/// <summary>
/// ForwardPERatio / Long-term Average Earning Growth Rate
/// </summary>
/// <remarks>
/// Morningstar DataId: 14021
/// </remarks>
[JsonProperty("14021")]
public double PEGRatio { get; set; }
/// <summary>
/// The number of years it would take for a company's cumulative earnings to equal the stock's current trading price, assuming that the company continues to increase its annual earnings at the growth rate used to calculate the PEG ratio. [ Log (PG/E + 1) / Log (1 + G) ] - 1 Where P=Price E=Next Fiscal Year's Estimated EPS G=Long-term Average Earning Growth
/// </summary>
/// <remarks>
/// Morningstar DataId: 14022
/// </remarks>
[JsonProperty("14022")]
public double PEGPayback { get; set; }
/// <summary>
/// The company's total book value less the value of any intangible assets dividend by number of shares.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14023
/// </remarks>
[JsonProperty("14023")]
public double TangibleBookValuePerShare { get; set; }
/// <summary>
/// The three year average for tangible book value per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14024
/// </remarks>
[JsonProperty("14024")]
public double TangibleBVPerShare3YrAvg { get; set; }
/// <summary>
/// The five year average for tangible book value per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14025
/// </remarks>
[JsonProperty("14025")]
public double TangibleBVPerShare5YrAvg { get; set; }
/// <summary>
/// Latest Dividend * Frequency
/// </summary>
/// <remarks>
/// Morningstar DataId: 14026
/// </remarks>
[JsonProperty("14026")]
public double ForwardDividend { get; set; }
/// <summary>
/// (Current Assets - Current Liabilities)/number of shares
/// </summary>
/// <remarks>
/// Morningstar DataId: 14027
/// </remarks>
[JsonProperty("14027")]
public double WorkingCapitalPerShare { get; set; }
/// <summary>
/// The three year average for working capital per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14028
/// </remarks>
[JsonProperty("14028")]
public double WorkingCapitalPerShare3YrAvg { get; set; }
/// <summary>
/// The five year average for working capital per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14029
/// </remarks>
[JsonProperty("14029")]
public double WorkingCapitalPerShare5YrAvg { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of EBITDA generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14030
/// </remarks>
[JsonProperty("14030")]
public double EVToEBITDA { get; set; }
/// <summary>
/// The net repurchase of shares outstanding over the market capital of the company. It is a measure of shareholder return.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14031
/// </remarks>
[JsonProperty("14031")]
public double BuyBackYield { get; set; }
/// <summary>
/// The total yield that shareholders can expect, by summing Dividend Yield and Buyback Yield.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14032
/// </remarks>
[JsonProperty("14032")]
public double TotalYield { get; set; }
/// <summary>
/// The five-year average of the company's price-to-earnings ratio.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14033
/// </remarks>
[JsonProperty("14033")]
public double RatioPE5YearAverage { get; set; }
/// <summary>
/// Price change this month, expressed as latest price/last month end price.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14034
/// </remarks>
[JsonProperty("14034")]
public double PriceChange1M { get; set; }
/// <summary>
/// Adjusted Close Price/ Normalized EPS. Normalized EPS removes onetime and unusual items from net EPS, to provide investors with a more accurate measure of the company's true earnings. If the result is negative, zero, >10,000 or <0.001, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14035
/// </remarks>
[JsonProperty("14035")]
public double NormalizedPERatio { get; set; }
/// <summary>
/// Adjusted close price/EBITDA Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14036
/// </remarks>
[JsonProperty("14036")]
public double PriceToEBITDA { get; set; }
/// <summary>
/// Average of the last 60 monthly observations of trailing dividend yield in the last 5 years.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14037
/// </remarks>
[JsonProperty("14037")]
public double DivYield5Year { get; set; }
/// <summary>
/// Estimated EPS/Book Value Per Share
/// </summary>
/// <remarks>
/// Morningstar DataId: 14038
/// </remarks>
[JsonProperty("14038")]
public double ForwardROE { get; set; }
/// <summary>
/// Estimated EPS/Total Assets Per Share
/// </summary>
/// <remarks>
/// Morningstar DataId: 14039
/// </remarks>
[JsonProperty("14039")]
public double ForwardROA { get; set; }
/// <summary>
/// 2 Years Forward Estimated EPS / Adjusted Close Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14040
/// </remarks>
[JsonProperty("14040")]
public double TwoYearsForwardEarningYield { get; set; }
/// <summary>
/// Adjusted Close Price/2 Years Forward Estimated EPS
/// </summary>
/// <remarks>
/// Morningstar DataId: 14041
/// </remarks>
[JsonProperty("14041")]
public double TwoYearsForwardPERatio { get; set; }
/// <summary>
/// Indicates the method used to calculate Forward Dividend. There are three options: Annual, Look-back and Manual.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14042
/// </remarks>
[JsonProperty("14042")]
public string ForwardCalculationStyle { get; set; }
/// <summary>
/// Used to collect the forward dividend for companies where our formula will not produce the correct value.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14043
/// </remarks>
[JsonProperty("14043")]
public double ActualForwardDividend { get; set; }
/// <summary>
/// Indicates the method used to calculate Trailing Dividend. There are two options: Look-back and Manual.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14044
/// </remarks>
[JsonProperty("14044")]
public string TrailingCalculationStyle { get; set; }
/// <summary>
/// Used to collect the trailing dividend for companies where our formula will not produce the correct value.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14045
/// </remarks>
[JsonProperty("14045")]
public double ActualTrailingDividend { get; set; }
/// <summary>
/// Total Assets / Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14046
/// </remarks>
[JsonProperty("14046")]
public double TotalAssetPerShare { get; set; }
/// <summary>
/// The growth rate from the TrailingDividend to the Forward Dividend: {(Forward Dividend/Trailing Dividend) - 1}*100.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14047
/// </remarks>
[JsonProperty("14047")]
public double ExpectedDividendGrowthRate { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of revenue generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14048
/// </remarks>
[JsonProperty("14048")]
public double EVToRevenue { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of Pretax Income generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14049
/// </remarks>
[JsonProperty("14049")]
public double EVToPreTaxIncome { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of asset value; should be the default EV multiple used in an asset driven business.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14050
/// </remarks>
[JsonProperty("14050")]
public double EVToTotalAssets { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of free cash flow generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14051
/// </remarks>
[JsonProperty("14051")]
public double EVToFCF { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of EBIT generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14052
/// </remarks>
[JsonProperty("14052")]
public double EVToEBIT { get; set; }
/// <summary>
/// Funds from operations per share; populated only for real estate investment trusts (REITs), defined as the sum of net income, gain/loss (realized and unrealized) on investment securities, asset impairment charge, depreciation and amortization and gain/ loss on the sale of business and property plant and equipment, divided by shares outstanding.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14053
/// </remarks>
[JsonProperty("14053")]
public double FFOPerShare { get; set; }
/// <summary>
/// The ratio of a stock's price to its cash flow per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14054
/// </remarks>
[JsonProperty("14054")]
public double PriceToCashRatio { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBITDA.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14055
/// </remarks>
[JsonProperty("14055")]
public double EVToForwardEBITDA { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated revenue.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14056
/// </remarks>
[JsonProperty("14056")]
public double EVToForwardRevenue { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBIT.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14057
/// </remarks>
[JsonProperty("14057")]
public double EVToForwardEBIT { get; set; }
/// <summary>
/// The one-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14058
/// </remarks>
[JsonProperty("14058")]
public double EVToEBITDA1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14059
/// </remarks>
[JsonProperty("14059")]
public double EVToFCF1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14060
/// </remarks>
[JsonProperty("14060")]
public double EVToRevenue1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14061
/// </remarks>
[JsonProperty("14061")]
public double EVToTotalAssets1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14062
/// </remarks>
[JsonProperty("14062")]
public double PFCFRatio1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14063
/// </remarks>
[JsonProperty("14063")]
public double PBRatio1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14064
/// </remarks>
[JsonProperty("14064")]
public double PERatio1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14065
/// </remarks>
[JsonProperty("14065")]
public double PSRatio1YearGrowth { get; set; }
/// <summary>
/// The three-year average for a company's EV to EBIT ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBIT (earnings minus expenses excluding interest and tax expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14066
/// </remarks>
[JsonProperty("14066")]
public double EVToEBIT3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to EBITDA ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14067
/// </remarks>
[JsonProperty("14067")]
public double EVToEBITDA3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to free cash flow ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash Flow from Operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14068
/// </remarks>
[JsonProperty("14068")]
public double EVToFCF3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to revenue ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14069
/// </remarks>
[JsonProperty("14069")]
public double EVToRevenue3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to total assets ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14070
/// </remarks>
[JsonProperty("14070")]
public double EVToTotalAssets3YrAvg { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to EBIT ratio. Morningstar calculates the growth percentage based on the EV to EBIT ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBIT (earnings minus expenses excluding interest and tax expenses) reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14071
/// </remarks>
[JsonProperty("14071")]
public double EVToEBIT3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to EBITDA ratio. Morningstar calculates the growth percentage based on the EV to EBITDA ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax depreciation and amortization expenses) reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14072
/// </remarks>
[JsonProperty("14072")]
public double EVToEBITDA3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to free cash flow ratio. Morningstar calculates the growth percentage based on the EV to free cash flow ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash Flow from Operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14073
/// </remarks>
[JsonProperty("14073")]
public double EVToFCF3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to revenue ratio. Morningstar calculates the growth percentage based on the EV to revenue ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14074
/// </remarks>
[JsonProperty("14074")]
public double EVToRevenue3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to total assets ratio. Morningstar calculates the growth percentage based on the EV to total assets ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14075
/// </remarks>
[JsonProperty("14075")]
public double EVToTotalAssets3YrAvgChange { get; set; }
/// <summary>
/// The three-year average for a company's price to free cash flow ratio (the adjusted close price divided by the free cash flow per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14076
/// </remarks>
[JsonProperty("14076")]
public double PFCFRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's price to book ratio (the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14077
/// </remarks>
[JsonProperty("14077")]
public double PBRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's price to sales ratio (the adjusted close price divided by the total sales per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14078
/// </remarks>
[JsonProperty("14078")]
public double PSRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's price to cash ratio (the adjusted close price divided by the cash flow per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14079
/// </remarks>
[JsonProperty("14079")]
public double PCashRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's PE ratio (the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14080
/// </remarks>
[JsonProperty("14080")]
public double PERatio3YrAvg { get; set; }
/// <summary>
/// The growth in the three-year average for a company's price to free cash flow ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14081
/// </remarks>
[JsonProperty("14081")]
public double PFCFRatio3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's price to book ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14082
/// </remarks>
[JsonProperty("14082")]
public double PBRatio3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's price to sales ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the total sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14083
/// </remarks>
[JsonProperty("14083")]
public double PSRatio3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's PE ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14084
/// </remarks>
[JsonProperty("14084")]
public double PERatio3YrAvgChange { get; set; }
/// <summary>
/// The one-year high for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14085
/// </remarks>
[JsonProperty("14085")]
public double PERatio1YearHigh { get; set; }
/// <summary>
/// The one-year low for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14086
/// </remarks>
[JsonProperty("14086")]
public double PERatio1YearLow { get; set; }
/// <summary>
/// The one-year average for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14087
/// </remarks>
[JsonProperty("14087")]
public double PERatio1YearAverage { get; set; }
/// <summary>
/// The five-year high for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14088
/// </remarks>
[JsonProperty("14088")]
public double PERatio5YearHigh { get; set; }
/// <summary>
/// The five-year low for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14089
/// </remarks>
[JsonProperty("14089")]
public double PERatio5YearLow { get; set; }
/// <summary>
/// The five-year average for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14090
/// </remarks>
[JsonProperty("14090")]
public double PERatio5YearAverage { get; set; }
/// <summary>
/// The ten-year high for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14091
/// </remarks>
[JsonProperty("14091")]
public double PERatio10YearHigh { get; set; }
/// <summary>
/// The ten-year low for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14092
/// </remarks>
[JsonProperty("14092")]
public double PERatio10YearLow { get; set; }
/// <summary>
/// The ten-year average for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14093
/// </remarks>
[JsonProperty("14093")]
public double PERatio10YearAverage { get; set; }
/// <summary>
/// The cyclically adjusted PE ratio for a company; adjusted close price divided by earnings per share. If the result is negative, zero, >10,000 or <0.001, then null. Morningstar uses the CPI index for US companies and Indexes from the World Bank for the rest of the global markets.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14094
/// </remarks>
[JsonProperty("14094")]
public double CAPERatio { get; set; }
/// <summary>
/// The three-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14095
/// </remarks>
[JsonProperty("14095")]
public double EVToEBITDA3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14096
/// </remarks>
[JsonProperty("14096")]
public double EVToFCF3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14097
/// </remarks>
[JsonProperty("14097")]
public double EVToRevenue3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14098
/// </remarks>
[JsonProperty("14098")]
public double EVToTotalAssets3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14099
/// </remarks>
[JsonProperty("14099")]
public double PFCFRatio3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14100
/// </remarks>
[JsonProperty("14100")]
public double PBRatio3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14101
/// </remarks>
[JsonProperty("14101")]
public double PERatio3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14102
/// </remarks>
[JsonProperty("14102")]
public double PSRatio3YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14103
/// </remarks>
[JsonProperty("14103")]
public double EVToEBITDA5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14104
/// </remarks>
[JsonProperty("14104")]
public double EVToFCF5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14105
/// </remarks>
[JsonProperty("14105")]
public double EVToRevenue5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14106
/// </remarks>
[JsonProperty("14106")]
public double EVToTotalAssets5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14107
/// </remarks>
[JsonProperty("14107")]
public double PFCFRatio5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14108
/// </remarks>
[JsonProperty("14108")]
public double PBRatio5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14109
/// </remarks>
[JsonProperty("14109")]
public double PERatio5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14110
/// </remarks>
[JsonProperty("14110")]
public double PSRatio5YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14111
/// </remarks>
[JsonProperty("14111")]
public double EVToEBITDA10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14112
/// </remarks>
[JsonProperty("14112")]
public double EVToFCF10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14113
/// </remarks>
[JsonProperty("14113")]
public double EVToRevenue10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14114
/// </remarks>
[JsonProperty("14114")]
public double EVToTotalAssets10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14115
/// </remarks>
[JsonProperty("14115")]
public double PFCFRatio10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14116
/// </remarks>
[JsonProperty("14116")]
public double PBRatio10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14117
/// </remarks>
[JsonProperty("14117")]
public double PERatio10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14118
/// </remarks>
[JsonProperty("14118")]
public double PSRatio10YearGrowth { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBIT in year 2.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14119
/// </remarks>
[JsonProperty("14119")]
public double TwoYrsEVToForwardEBIT { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBITDA in year 2.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14120
/// </remarks>
[JsonProperty("14120")]
public double TwoYrsEVToForwardEBITDA { get; set; }
/// <summary>
/// EPS Growth Ratio: (Estimated EPS Year 1) / (TTM Normalized diluted EPS
/// </summary>
/// <remarks>
/// Morningstar DataId: 14121
/// </remarks>
[JsonProperty("14121")]
public double FirstYearEstimatedEPSGrowth { get; set; }
/// <summary>
/// EPS Growth Ratio: (Estimated EPS Year 2) / (Estimated EPS Year 1)
/// </summary>
/// <remarks>
/// Morningstar DataId: 14122
/// </remarks>
[JsonProperty("14122")]
public double SecondYearEstimatedEPSGrowth { get; set; }
/// <summary>
/// Normalized ForwardPERatio / Long-term Average Normalized Earnings Growth Rate
/// </summary>
/// <remarks>
/// Morningstar DataId: 14123
/// </remarks>
[JsonProperty("14123")]
public double NormalizedPEGRatio { get; set; }
/// <summary>
/// Creates a new instance for the given time and security
/// </summary>
public ValuationRatios(ITimeProvider timeProvider, SecurityIdentifier securityIdentifier)
: base(timeProvider, securityIdentifier)
{
}
/// <summary>
/// Clones this instance
/// </summary>
public override FundamentalTimeDependentProperty Clone(ITimeProvider timeProvider)
{
return new ValuationRatios(timeProvider, _securityIdentifier);
}
}
}
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2023 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Linq;
using Python.Runtime;
using Newtonsoft.Json;
using System.Collections.Generic;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Data.Fundamental
{
/// <summary>
/// Definition of the ValuationRatios class
/// </summary>
public class ValuationRatiosExt
{
/// <summary>
/// Dividend per share / Diluted earnings per share
/// </summary>
/// <remarks>
/// Morningstar DataId: 14000
/// </remarks>
[JsonProperty("14000")]
public double PayoutRatio { get; set; }
/// <summary>
/// ROE * (1 - Payout Ratio)
/// </summary>
/// <remarks>
/// Morningstar DataId: 14001
/// </remarks>
[JsonProperty("14001")]
public double SustainableGrowthRate { get; set; }
/// <summary>
/// Refers to the ratio of free cash flow to enterprise value. Morningstar calculates the ratio by using the underlying data reported in the company filings or reports: FCF /Enterprise Value.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14002
/// </remarks>
[JsonProperty("14002")]
public double CashReturn { get; set; }
/// <summary>
/// Sales / Average Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14003
/// </remarks>
[JsonProperty("14003")]
public double SalesPerShare { get; set; }
/// <summary>
/// Common Shareholder's Equity / Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14004
/// </remarks>
[JsonProperty("14004")]
public double BookValuePerShare { get; set; }
/// <summary>
/// Cash Flow from Operations / Average Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14005
/// </remarks>
[JsonProperty("14005")]
public double CFOPerShare { get; set; }
/// <summary>
/// Free Cash Flow / Average Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14006
/// </remarks>
[JsonProperty("14006")]
public double FCFPerShare { get; set; }
/// <summary>
/// Diluted EPS / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14007
/// </remarks>
[JsonProperty("14007")]
public double EarningYield { get; set; }
/// <summary>
/// Adjusted Close Price/ EPS. If the result is negative, zero, >10,000 or <0.001, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14008
/// </remarks>
[JsonProperty("14008")]
public double PERatio { get; set; }
/// <summary>
/// SalesPerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14009
/// </remarks>
[JsonProperty("14009")]
public double SalesYield { get; set; }
/// <summary>
/// Adjusted close price / Sales Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14010
/// </remarks>
[JsonProperty("14010")]
public double PSRatio { get; set; }
/// <summary>
/// BookValuePerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14011
/// </remarks>
[JsonProperty("14011")]
public double BookValueYield { get; set; }
/// <summary>
/// Adjusted close price / Book Value Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14012
/// </remarks>
[JsonProperty("14012")]
public double PBRatio { get; set; }
/// <summary>
/// CFOPerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14013
/// </remarks>
[JsonProperty("14013")]
public double CFYield { get; set; }
/// <summary>
/// Adjusted close price /Cash Flow Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14014
/// </remarks>
[JsonProperty("14014")]
public double PCFRatio { get; set; }
/// <summary>
/// FCFPerShare / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14015
/// </remarks>
[JsonProperty("14015")]
public double FCFYield { get; set; }
/// <summary>
/// Adjusted close price/ Free Cash Flow Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14016
/// </remarks>
[JsonProperty("14016")]
public double FCFRatio { get; set; }
/// <summary>
/// Dividends Per Share over the trailing 12 months / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14017
/// </remarks>
[JsonProperty("14017")]
public double TrailingDividendYield { get; set; }
/// <summary>
/// (Current Dividend Per Share * Payout Frequency) / Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14018
/// </remarks>
[JsonProperty("14018")]
public double ForwardDividendYield { get; set; }
/// <summary>
/// Estimated Earnings Per Share / Price Note: a) The "Next" Year's EPS Estimate is used; For instance, if today's actual date is March 1, 2009, the "Current" EPS Estimate for MSFT is June 2009, and the "Next" EPS Estimate for MSFT is June 2010; the latter is used. b) The eps estimated data is sourced from a third party.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14019
/// </remarks>
[JsonProperty("14019")]
public double ForwardEarningYield { get; set; }
/// <summary>
/// 1 / ForwardEarningYield If result is negative, then null
/// </summary>
/// <remarks>
/// Morningstar DataId: 14020
/// </remarks>
[JsonProperty("14020")]
public double ForwardPERatio { get; set; }
/// <summary>
/// ForwardPERatio / Long-term Average Earning Growth Rate
/// </summary>
/// <remarks>
/// Morningstar DataId: 14021
/// </remarks>
[JsonProperty("14021")]
public double PEGRatio { get; set; }
/// <summary>
/// The number of years it would take for a company's cumulative earnings to equal the stock's current trading price, assuming that the company continues to increase its annual earnings at the growth rate used to calculate the PEG ratio. [ Log (PG/E + 1) / Log (1 + G) ] - 1 Where P=Price E=Next Fiscal Year's Estimated EPS G=Long-term Average Earning Growth
/// </summary>
/// <remarks>
/// Morningstar DataId: 14022
/// </remarks>
[JsonProperty("14022")]
public double PEGPayback { get; set; }
/// <summary>
/// The company's total book value less the value of any intangible assets dividend by number of shares.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14023
/// </remarks>
[JsonProperty("14023")]
public double TangibleBookValuePerShare { get; set; }
/// <summary>
/// The three year average for tangible book value per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14024
/// </remarks>
[JsonProperty("14024")]
public double TangibleBVPerShare3YrAvg { get; set; }
/// <summary>
/// The five year average for tangible book value per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14025
/// </remarks>
[JsonProperty("14025")]
public double TangibleBVPerShare5YrAvg { get; set; }
/// <summary>
/// Latest Dividend * Frequency
/// </summary>
/// <remarks>
/// Morningstar DataId: 14026
/// </remarks>
[JsonProperty("14026")]
public double ForwardDividend { get; set; }
/// <summary>
/// (Current Assets - Current Liabilities)/number of shares
/// </summary>
/// <remarks>
/// Morningstar DataId: 14027
/// </remarks>
[JsonProperty("14027")]
public double WorkingCapitalPerShare { get; set; }
/// <summary>
/// The three year average for working capital per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14028
/// </remarks>
[JsonProperty("14028")]
public double WorkingCapitalPerShare3YrAvg { get; set; }
/// <summary>
/// The five year average for working capital per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14029
/// </remarks>
[JsonProperty("14029")]
public double WorkingCapitalPerShare5YrAvg { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of EBITDA generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14030
/// </remarks>
[JsonProperty("14030")]
public double EVToEBITDA { get; set; }
/// <summary>
/// The net repurchase of shares outstanding over the market capital of the company. It is a measure of shareholder return.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14031
/// </remarks>
[JsonProperty("14031")]
public double BuyBackYield { get; set; }
/// <summary>
/// The total yield that shareholders can expect, by summing Dividend Yield and Buyback Yield.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14032
/// </remarks>
[JsonProperty("14032")]
public double TotalYield { get; set; }
/// <summary>
/// The five-year average of the company's price-to-earnings ratio.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14033
/// </remarks>
[JsonProperty("14033")]
public double RatioPE5YearAverage { get; set; }
/// <summary>
/// Price change this month, expressed as latest price/last month end price.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14034
/// </remarks>
[JsonProperty("14034")]
public double PriceChange1M { get; set; }
/// <summary>
/// Adjusted Close Price/ Normalized EPS. Normalized EPS removes onetime and unusual items from net EPS, to provide investors with a more accurate measure of the company's true earnings. If the result is negative, zero, >10,000 or <0.001, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14035
/// </remarks>
[JsonProperty("14035")]
public double NormalizedPERatio { get; set; }
/// <summary>
/// Adjusted close price/EBITDA Per Share. If the result is negative or zero, then null.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14036
/// </remarks>
[JsonProperty("14036")]
public double PriceToEBITDA { get; set; }
/// <summary>
/// Average of the last 60 monthly observations of trailing dividend yield in the last 5 years.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14037
/// </remarks>
[JsonProperty("14037")]
public double DivYield5Year { get; set; }
/// <summary>
/// Estimated EPS/Book Value Per Share
/// </summary>
/// <remarks>
/// Morningstar DataId: 14038
/// </remarks>
[JsonProperty("14038")]
public double ForwardROE { get; set; }
/// <summary>
/// Estimated EPS/Total Assets Per Share
/// </summary>
/// <remarks>
/// Morningstar DataId: 14039
/// </remarks>
[JsonProperty("14039")]
public double ForwardROA { get; set; }
/// <summary>
/// 2 Years Forward Estimated EPS / Adjusted Close Price
/// </summary>
/// <remarks>
/// Morningstar DataId: 14040
/// </remarks>
[JsonProperty("14040")]
public double TwoYearsForwardEarningYield { get; set; }
/// <summary>
/// Adjusted Close Price/2 Years Forward Estimated EPS
/// </summary>
/// <remarks>
/// Morningstar DataId: 14041
/// </remarks>
[JsonProperty("14041")]
public double TwoYearsForwardPERatio { get; set; }
/// <summary>
/// Indicates the method used to calculate Forward Dividend. There are three options: Annual, Look-back and Manual.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14042
/// </remarks>
[JsonProperty("14042")]
public string ForwardCalculationStyle { get; set; }
/// <summary>
/// Used to collect the forward dividend for companies where our formula will not produce the correct value.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14043
/// </remarks>
[JsonProperty("14043")]
public double ActualForwardDividend { get; set; }
/// <summary>
/// Indicates the method used to calculate Trailing Dividend. There are two options: Look-back and Manual.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14044
/// </remarks>
[JsonProperty("14044")]
public string TrailingCalculationStyle { get; set; }
/// <summary>
/// Used to collect the trailing dividend for companies where our formula will not produce the correct value.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14045
/// </remarks>
[JsonProperty("14045")]
public double ActualTrailingDividend { get; set; }
/// <summary>
/// Total Assets / Diluted Shares Outstanding
/// </summary>
/// <remarks>
/// Morningstar DataId: 14046
/// </remarks>
[JsonProperty("14046")]
public double TotalAssetPerShare { get; set; }
/// <summary>
/// The growth rate from the TrailingDividend to the Forward Dividend: {(Forward Dividend/Trailing Dividend) - 1}*100.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14047
/// </remarks>
[JsonProperty("14047")]
public double ExpectedDividendGrowthRate { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of revenue generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14048
/// </remarks>
[JsonProperty("14048")]
public double EVToRevenue { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of Pretax Income generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14049
/// </remarks>
[JsonProperty("14049")]
public double EVToPreTaxIncome { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of asset value; should be the default EV multiple used in an asset driven business.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14050
/// </remarks>
[JsonProperty("14050")]
public double EVToTotalAssets { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of free cash flow generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14051
/// </remarks>
[JsonProperty("14051")]
public double EVToFCF { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of EBIT generated.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14052
/// </remarks>
[JsonProperty("14052")]
public double EVToEBIT { get; set; }
/// <summary>
/// Funds from operations per share; populated only for real estate investment trusts (REITs), defined as the sum of net income, gain/loss (realized and unrealized) on investment securities, asset impairment charge, depreciation and amortization and gain/ loss on the sale of business and property plant and equipment, divided by shares outstanding.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14053
/// </remarks>
[JsonProperty("14053")]
public double FFOPerShare { get; set; }
/// <summary>
/// The ratio of a stock's price to its cash flow per share.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14054
/// </remarks>
[JsonProperty("14054")]
public double PriceToCashRatio { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBITDA.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14055
/// </remarks>
[JsonProperty("14055")]
public double EVToForwardEBITDA { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated revenue.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14056
/// </remarks>
[JsonProperty("14056")]
public double EVToForwardRevenue { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBIT.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14057
/// </remarks>
[JsonProperty("14057")]
public double EVToForwardEBIT { get; set; }
/// <summary>
/// The one-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14058
/// </remarks>
[JsonProperty("14058")]
public double EVToEBITDA1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14059
/// </remarks>
[JsonProperty("14059")]
public double EVToFCF1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14060
/// </remarks>
[JsonProperty("14060")]
public double EVToRevenue1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14061
/// </remarks>
[JsonProperty("14061")]
public double EVToTotalAssets1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14062
/// </remarks>
[JsonProperty("14062")]
public double PFCFRatio1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14063
/// </remarks>
[JsonProperty("14063")]
public double PBRatio1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14064
/// </remarks>
[JsonProperty("14064")]
public double PERatio1YearGrowth { get; set; }
/// <summary>
/// The one-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14065
/// </remarks>
[JsonProperty("14065")]
public double PSRatio1YearGrowth { get; set; }
/// <summary>
/// The three-year average for a company's EV to EBIT ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBIT (earnings minus expenses excluding interest and tax expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14066
/// </remarks>
[JsonProperty("14066")]
public double EVToEBIT3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to EBITDA ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14067
/// </remarks>
[JsonProperty("14067")]
public double EVToEBITDA3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to free cash flow ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash Flow from Operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14068
/// </remarks>
[JsonProperty("14068")]
public double EVToFCF3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to revenue ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14069
/// </remarks>
[JsonProperty("14069")]
public double EVToRevenue3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's EV to total assets ratio: EV (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14070
/// </remarks>
[JsonProperty("14070")]
public double EVToTotalAssets3YrAvg { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to EBIT ratio. Morningstar calculates the growth percentage based on the EV to EBIT ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBIT (earnings minus expenses excluding interest and tax expenses) reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14071
/// </remarks>
[JsonProperty("14071")]
public double EVToEBIT3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to EBITDA ratio. Morningstar calculates the growth percentage based on the EV to EBITDA ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax depreciation and amortization expenses) reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14072
/// </remarks>
[JsonProperty("14072")]
public double EVToEBITDA3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to free cash flow ratio. Morningstar calculates the growth percentage based on the EV to free cash flow ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash Flow from Operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14073
/// </remarks>
[JsonProperty("14073")]
public double EVToFCF3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to revenue ratio. Morningstar calculates the growth percentage based on the EV to revenue ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14074
/// </remarks>
[JsonProperty("14074")]
public double EVToRevenue3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's EV to total assets ratio. Morningstar calculates the growth percentage based on the EV to total assets ratio ((Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14075
/// </remarks>
[JsonProperty("14075")]
public double EVToTotalAssets3YrAvgChange { get; set; }
/// <summary>
/// The three-year average for a company's price to free cash flow ratio (the adjusted close price divided by the free cash flow per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14076
/// </remarks>
[JsonProperty("14076")]
public double PFCFRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's price to book ratio (the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14077
/// </remarks>
[JsonProperty("14077")]
public double PBRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's price to sales ratio (the adjusted close price divided by the total sales per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14078
/// </remarks>
[JsonProperty("14078")]
public double PSRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's price to cash ratio (the adjusted close price divided by the cash flow per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14079
/// </remarks>
[JsonProperty("14079")]
public double PCashRatio3YrAvg { get; set; }
/// <summary>
/// The three-year average for a company's PE ratio (the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14080
/// </remarks>
[JsonProperty("14080")]
public double PERatio3YrAvg { get; set; }
/// <summary>
/// The growth in the three-year average for a company's price to free cash flow ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14081
/// </remarks>
[JsonProperty("14081")]
public double PFCFRatio3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's price to book ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14082
/// </remarks>
[JsonProperty("14082")]
public double PBRatio3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's price to sales ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the total sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14083
/// </remarks>
[JsonProperty("14083")]
public double PSRatio3YrAvgChange { get; set; }
/// <summary>
/// The growth in the three-year average for a company's PE ratio. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14084
/// </remarks>
[JsonProperty("14084")]
public double PERatio3YrAvgChange { get; set; }
/// <summary>
/// The one-year high for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14085
/// </remarks>
[JsonProperty("14085")]
public double PERatio1YearHigh { get; set; }
/// <summary>
/// The one-year low for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14086
/// </remarks>
[JsonProperty("14086")]
public double PERatio1YearLow { get; set; }
/// <summary>
/// The one-year average for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14087
/// </remarks>
[JsonProperty("14087")]
public double PERatio1YearAverage { get; set; }
/// <summary>
/// The five-year high for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14088
/// </remarks>
[JsonProperty("14088")]
public double PERatio5YearHigh { get; set; }
/// <summary>
/// The five-year low for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14089
/// </remarks>
[JsonProperty("14089")]
public double PERatio5YearLow { get; set; }
/// <summary>
/// The five-year average for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14090
/// </remarks>
[JsonProperty("14090")]
public double PERatio5YearAverage { get; set; }
/// <summary>
/// The ten-year high for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14091
/// </remarks>
[JsonProperty("14091")]
public double PERatio10YearHigh { get; set; }
/// <summary>
/// The ten-year low for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14092
/// </remarks>
[JsonProperty("14092")]
public double PERatio10YearLow { get; set; }
/// <summary>
/// The ten-year average for a company's PE ratio (adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports).
/// </summary>
/// <remarks>
/// Morningstar DataId: 14093
/// </remarks>
[JsonProperty("14093")]
public double PERatio10YearAverage { get; set; }
/// <summary>
/// The cyclically adjusted PE ratio for a company; adjusted close price divided by earnings per share. If the result is negative, zero, >10,000 or <0.001, then null. Morningstar uses the CPI index for US companies and Indexes from the World Bank for the rest of the global markets.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14094
/// </remarks>
[JsonProperty("14094")]
public double CAPERatio { get; set; }
/// <summary>
/// The three-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14095
/// </remarks>
[JsonProperty("14095")]
public double EVToEBITDA3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14096
/// </remarks>
[JsonProperty("14096")]
public double EVToFCF3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14097
/// </remarks>
[JsonProperty("14097")]
public double EVToRevenue3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14098
/// </remarks>
[JsonProperty("14098")]
public double EVToTotalAssets3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14099
/// </remarks>
[JsonProperty("14099")]
public double PFCFRatio3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14100
/// </remarks>
[JsonProperty("14100")]
public double PBRatio3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14101
/// </remarks>
[JsonProperty("14101")]
public double PERatio3YearGrowth { get; set; }
/// <summary>
/// The three-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14102
/// </remarks>
[JsonProperty("14102")]
public double PSRatio3YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14103
/// </remarks>
[JsonProperty("14103")]
public double EVToEBITDA5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14104
/// </remarks>
[JsonProperty("14104")]
public double EVToFCF5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14105
/// </remarks>
[JsonProperty("14105")]
public double EVToRevenue5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14106
/// </remarks>
[JsonProperty("14106")]
public double EVToTotalAssets5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14107
/// </remarks>
[JsonProperty("14107")]
public double PFCFRatio5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14108
/// </remarks>
[JsonProperty("14108")]
public double PBRatio5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14109
/// </remarks>
[JsonProperty("14109")]
public double PERatio5YearGrowth { get; set; }
/// <summary>
/// The five-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14110
/// </remarks>
[JsonProperty("14110")]
public double PSRatio5YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to EBITDA on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by EBITDA (earnings minus expenses excluding interest, tax, depreciation, and amortization expenses) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14111
/// </remarks>
[JsonProperty("14111")]
public double EVToEBITDA10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to free cash flow on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by free cash flow (Cash flow from operations - Capital Expenditures) reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14112
/// </remarks>
[JsonProperty("14112")]
public double EVToFCF10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to revenue on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by Total Revenue reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14113
/// </remarks>
[JsonProperty("14113")]
public double EVToRevenue10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's EV to total assets on a percentage basis. Morningstar calculates the growth percentage based on the enterprise value (Market Cap + Preferred stock + Long-Term Debt And Capital Lease + Short Term Debt And Capital Lease + Securities Sold But Not Yet Repurchased - Cash, Cash Equivalent And Market Securities - Securities Purchased with Agreement to Resell - Securities Borrowed) divided by total assets reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14114
/// </remarks>
[JsonProperty("14114")]
public double EVToTotalAssets10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's price to free cash flow ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the free cash flow reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14115
/// </remarks>
[JsonProperty("14115")]
public double PFCFRatio10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's price to book ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the book value per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14116
/// </remarks>
[JsonProperty("14116")]
public double PBRatio10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's PE ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the earnings per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14117
/// </remarks>
[JsonProperty("14117")]
public double PERatio10YearGrowth { get; set; }
/// <summary>
/// The ten-year growth in the company's price to sales ratio on a percentage basis. Morningstar calculates the growth percentage based on the adjusted close price divided by the sales per share reported in the Financial Statements within the company filings or reports.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14118
/// </remarks>
[JsonProperty("14118")]
public double PSRatio10YearGrowth { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBIT in year 2.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14119
/// </remarks>
[JsonProperty("14119")]
public double TwoYrsEVToForwardEBIT { get; set; }
/// <summary>
/// Indicates what is a company being valued per each dollar of estimated EBITDA in year 2.
/// </summary>
/// <remarks>
/// Morningstar DataId: 14120
/// </remarks>
[JsonProperty("14120")]
public double TwoYrsEVToForwardEBITDA { get; set; }
/// <summary>
/// EPS Growth Ratio: (Estimated EPS Year 1) / (TTM Normalized diluted EPS
/// </summary>
/// <remarks>
/// Morningstar DataId: 14121
/// </remarks>
[JsonProperty("14121")]
public double FirstYearEstimatedEPSGrowth { get; set; }
/// <summary>
/// EPS Growth Ratio: (Estimated EPS Year 2) / (Estimated EPS Year 1)
/// </summary>
/// <remarks>
/// Morningstar DataId: 14122
/// </remarks>
[JsonProperty("14122")]
public double SecondYearEstimatedEPSGrowth { get; set; }
/// <summary>
/// Normalized ForwardPERatio / Long-term Average Normalized Earnings Growth Rate
/// </summary>
/// <remarks>
/// Morningstar DataId: 14123
/// </remarks>
[JsonProperty("14123")]
public double NormalizedPEGRatio { get; set; }
/// <summary>
/// Creates a new instance for the given time and security
/// </summary>
public ValuationRatiosExt()
{
}
}
}
D:\Lean-16863\ToolBox\CoarseUniverseGenerator\CoarseUniverseGeneratorProgram.cs修改
Parallel.ForEach(outputCoarseContent, coarseByDate =>
{
var filename = $"{coarseByDate.Key.ToString(DateFormat.EightCharacter, CultureInfo.InvariantCulture)}.csv";
var filePath = Path.Combine(_destinationFolder.FullName, filename);
Log.Debug($"CoarseUniverseGeneratorProgram.Run(): Saving {filename} with {coarseByDate.Value.Count} entries.");
/此行作用是写入新因子值
File.WriteAllLines(filePath, coarseByDate.Value.Select(x => CoarseFundamentalExt.ToRowExt(x)).OrderBy(cr => cr));
var filesCount = Interlocked.Increment(ref coarseFilesGenerated);
if (filesCount % 1000 == 0)
{
var elapsed = DateTime.UtcNow - startWriting;
Log.Trace($"CoarseUniverseGeneratorProgram.Run(): Processed {filesCount} in {elapsed:g} at {filesCount / elapsed.TotalSeconds:F2} files/second ");
}
});
修改D:\Lean-16863\Common\Data\Fundamental\FundamentalInstanceProvider.cs
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2023 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Fasterflect;
using QuantConnect.Configuration;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Interfaces;
using QuantConnect.Util;
using static QuantConnect.Data.UniverseSelection.CoarseFundamentalDataProviderExt;
namespace QuantConnect.Data.Fundamental
{
/// <summary>
/// Per symbol we will have a fundamental class provider so the instances can be reused
/// </summary>
public class FundamentalInstanceProvider
{
private static readonly Dictionary<SecurityIdentifier, FundamentalInstanceProvider> _cache = new();
private readonly FundamentalTimeProvider _timeProvider;
private readonly FinancialStatements _financialStatements;
private readonly OperationRatios _operationRatios;
private readonly SecurityReference _securityReference;
private readonly CompanyReference _companyReference;
private readonly CompanyProfile _companyProfile;
private readonly AssetClassification _assetClassification;
private ValuationRatios _valuationRatios;
private readonly EarningRatios _earningRatios;
private readonly EarningReports _earningReports;
private DateTime _date;
private Symbol _symbol;
public static IDataProvider dataProvider;
/// <summary>
/// Get's the fundamental instance provider for the requested symbol
/// </summary>
/// <param name="symbol">The requested symbol</param>
/// <returns>The unique instance provider</returns>
public static FundamentalInstanceProvider Get(Symbol symbol)
{
FundamentalInstanceProvider result = null;
lock (_cache)
{
_cache.TryGetValue(symbol.ID, out result);
}
if (result == null)
{
// we create the fundamental instance provider without holding the cache lock, this is because it uses the pygil
// Deadlock case: if the main thread has PyGil and wants to take lock on cache (security.Fundamentals use case) and the data
// stack thread takes the lock on the cache (creating new fundamentals) and next wants the pygil deadlock!
result = new FundamentalInstanceProvider(symbol);
lock (_cache)
{
_cache[symbol.ID] = result;
}
}
return result;
}
/// <summary>
/// Creates a new fundamental instance provider
/// </summary>
/// <param name="symbol">The target symbol</param>
private FundamentalInstanceProvider(Symbol symbol)
{
_timeProvider = new();
_financialStatements = new(_timeProvider, symbol.ID);
_operationRatios = new(_timeProvider, symbol.ID);
_securityReference = new(_timeProvider, symbol.ID);
_companyReference = new(_timeProvider, symbol.ID);
_companyProfile = new(_timeProvider, symbol.ID);
_assetClassification = new(_timeProvider, symbol.ID);
_valuationRatios = new(_timeProvider, symbol.ID);
_earningRatios = new(_timeProvider, symbol.ID);
_earningReports = new(_timeProvider, symbol.ID);
}
/// <summary>
/// Returns the ValuationRatios instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValuationRatios GetValuationRatios(DateTime time, Symbol symbol)
{
_timeProvider.Time = time;
if (time == _date)
{
return _valuationRatios;
}
_date = time;
var path = Path.Combine(Globals.DataFolder, "equity", "usa", "fundamental", "coarse", $"{time:yyyyMMdd}.csv");
var fileStream = dataProvider.Fetch(path);
if (fileStream == null)
{
return _valuationRatios;
}
//_coarseFundamental.Clear();
using (var reader = new StreamReader(fileStream))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var csv = line.Split(',');
if (csv[1] != symbol.Value)
{
continue;
}
else
{
Read(line, time);
break;
}
}
}
return _valuationRatios;
}
private void Read(string line, DateTime time)
{
try
{
var csv = line.Split(',');
if (csv.Length > 8)
{
Type type = typeof(ValuationRatios);
PropertyInfo[] propertyInfos = type.GetProperties().Where(p => p.PropertyType == typeof(double)).ToArray();
for (int i = 8, j = 0; (i < csv.Length) && (j < propertyInfos.Length); i++, j++)
{
_valuationRatios.SetPropertyValue(propertyInfos[j].Name, double.Parse(csv[i]));
}
var d = 0;
}
}
catch (Exception ex)
{
var msg = ex.Message;
}
}
/// <summary>
/// Returns the EarningRatios instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EarningRatios GetEarningRatios(DateTime time)
{
_timeProvider.Time = time;
return _earningRatios;
}
/// <summary>
/// Returns the EarningReports instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EarningReports GetEarningReports(DateTime time)
{
_timeProvider.Time = time;
return _earningReports;
}
/// <summary>
/// Returns the OperationRatios instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public OperationRatios GetOperationRatios(DateTime time)
{
_timeProvider.Time = time;
return _operationRatios;
}
/// <summary>
/// Returns the FinancialStatements instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public FinancialStatements GetFinancialStatements(DateTime time)
{
_timeProvider.Time = time;
return _financialStatements;
}
/// <summary>
/// Returns the SecurityReference instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public SecurityReference GetSecurityReference(DateTime time)
{
_timeProvider.Time = time;
return _securityReference;
}
/// <summary>
/// Returns the CompanyReference instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CompanyReference GetCompanyReference(DateTime time)
{
_timeProvider.Time = time;
return _companyReference;
}
/// <summary>
/// Returns the CompanyProfile instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CompanyProfile GetCompanyProfile(DateTime time)
{
_timeProvider.Time = time;
return _companyProfile;
}
/// <summary>
/// Returns the AssetClassification instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AssetClassification GetAssetClassification(DateTime time)
{
_timeProvider.Time = time;
return _assetClassification;
}
private class FundamentalTimeProvider : ITimeProvider
{
public DateTime Time;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public DateTime GetUtcNow() => Time;
}
}
}
修改D:\Lean-16863\Common\Data\UniverseSelection\FundamentalService.cs传递DataProvider
/// <summary>
/// Initializes the service
/// </summary>
/// <param name="dataProvider">The data provider instance to use</param>
/// <param name="liveMode">True if running in live mode</param>
public static void Initialize(IDataProvider dataProvider, bool liveMode)
{
///传递
FundamentalInstanceProvider.dataProvider = dataProvider;
Initialize(dataProvider, Config.Get("fundamental-data-provider", nameof(CoarseFineFundamentalDataProvider)), liveMode);
}
测试策略CoarseFineFundamentalComboAlgorithm.cs
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Demonstration of how to define a universe filtered by the combination of coarse
/// fundamental data and fine fundamental data. This lets you do a first pass based on the asset volume; then later
/// select based on the company fundamentals.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="universes" />
/// <meta name="tag" content="coarse universes" />
/// <meta name="tag" content="fine universes" />
public class CoarseFineFundamentalComboAlgorithm : QCAlgorithm
{
private const int NumberOfSymbolsCoarse = 5;
private const int NumberOfSymbolsFine = 2;
// initialize our changes to nothing
private SecurityChanges _changes = SecurityChanges.None;
public override void Initialize()
{
UniverseSettings.Resolution = Resolution.Daily;
SetStartDate(2014, 04, 01);
SetEndDate(2014, 04, 30);
SetCash(50000);
// this add universe method accepts two parameters:
// - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol>
// - fine selection function: accepts an IEnumerable<FineFundamental> and returns an IEnumerable<Symbol>
AddUniverse(CoarseSelectionFunction, FineSelectionFunction);
}
// sort the data by daily dollar volume and take the top 'NumberOfSymbolsCoarse'
public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse)
{
// select only symbols with fundamental data and sort descending by daily dollar volume
var sortedByDollarVolume = coarse
.Where(x => x.HasFundamentalData)
.OrderByDescending(x => x.DollarVolume);
// take the top entries from our sorted collection
var top5 = sortedByDollarVolume.Take(NumberOfSymbolsCoarse);
// we need to return only the symbol objects
return top5.Select(x => x.Symbol);
}
// sort the data by P/E ratio and take the top 'NumberOfSymbolsFine'
public IEnumerable<Symbol> FineSelectionFunction(IEnumerable<FineFundamental> fine)
{
// sort descending by P/E ratio
var sortedByPeRatio = fine.OrderByDescending(x => x.ValuationRatios.PERatio);
// take the top entries from our sorted collection
var topFine = sortedByPeRatio.Take(NumberOfSymbolsFine);
foreach (var symbol in topFine)
{
Error("--------------------------------------------------");
Error(symbol.Time.ToString());
Error(string.Format("symbol={0}, peratio={1}", symbol.Symbol, symbol.ValuationRatios.PERatio));
Error("--------------------------------------------------");
}
// we need to return only the symbol objects
return topFine.Select(x => x.Symbol);
}
//Data Event Handler: New data arrives here.
public override void OnData(Slice slice)
{
// if we have no changes, do nothing
if (_changes == SecurityChanges.None) return;
// liquidate removed securities
foreach (var security in _changes.RemovedSecurities)
{
if (security.Invested)
{
Liquidate(security.Symbol);
Debug("Liquidated Stock: " + security.Symbol.Value);
}
}
// we want 50% allocation in each security in our universe
foreach (var security in _changes.AddedSecurities)
{
SetHoldings(security.Symbol, 0.5m);
Debug("Purchased Stock: " + security.Symbol.Value);
}
_changes = SecurityChanges.None;
}
// this event fires whenever we have changes to our universe
public override void OnSecuritiesChanged(SecurityChanges changes)
{
_changes = changes;
if (changes.AddedSecurities.Count > 0)
{
Debug("Securities added: " + string.Join(",", changes.AddedSecurities.Select(x => x.Symbol.Value)));
}
if (changes.RemovedSecurities.Count > 0)
{
Debug("Securities removed: " + string.Join(",", changes.RemovedSecurities.Select(x => x.Symbol.Value)));
}
}
}
}
可见随机生成的因子值可以被策略读取了,从而行情数据、基本面数据完成全部随机生成,基本可以支持多类型策略