Hi QC forum

I am experiencing some problems trying to merge some fundamental data dataframe, with an dataframe of returns of the same stocks. I want a nice and clean dataframe with both fundamental data, and return of different stocks. The problem is only in the backtest environment, and not in research. The code for the research is as following

  1. qb = QuantBook()
  2. tickers = ("AAPL", "MSFT", "AMZN", "TSLA", "GOOGL", "FB", "NVDA", "BRK.B", "UNH", "JNJ", "PG", "HD", "V",
  3. "BAC", "MA", "XOM", "PFE", "DIS", "CVX", "PEP", "CSCO", "ADBE", "KO", "ABBV", "TMO", "CMCSA", "ABT", "VZ", "AVGO")
  4. symbols = [qb.AddEquity(ticker, Resolution.Daily).Symbol for ticker in tickers]
  5. start_time = datetime(2017, 1, 2)
  6. end_time = datetime(2020, 1, 2)
  7. funda_start = datetime(2020, 1, 1)
  8. funda_end = datetime(2020, 1, 2)
  9. fundamentals = ["ValuationRatios.SustainableGrowthRate", "ValuationRatios.PayoutRatio", "ValuationRatios.CashReturn", "ValuationRatios.FCFRatio", "ValuationRatios.EarningYield", "ValuationRatios.SalesYield", "ValuationRatios.BookValueYield", "ValuationRatios.PBRatio",
  10. "ValuationRatios.PEGRatio", "ValuationRatios.BuyBackYield", "ValuationRatios.PricetoEBITDA", "ValuationRatios.ForwardPERatio", "ValuationRatios.EVToEBITDA3YrAvgChange",
  11. "ValuationRatios.EVtoFCF", "ValuationRatios.EVtoEBIT", "ValuationRatios.EVToForwardEBITDA", "ValuationRatios.EVToForwardRevenue", "ValuationRatios.ForwardROE",
  12. "ValuationRatios.ForwardDividend"]
  13. ratios = pd.DataFrame()
  14. for fundamental in fundamentals:
  15. ratio = qb.GetFundamental(symbols, fundamental, funda_start, funda_end)
  16. ratio.columns = pd.MultiIndex.from_tuples([(fundamental, x) for x in ratio.columns])
  17. ratios = pd.concat([ratios, ratio], axis = 1)
  18. dataframe = ratios.stack().reset_index()
  19. dataframe.drop(["level_0"], axis=1, inplace = True)
  20. dataframe = dataframe.set_index(keys = dataframe.level_1).drop(['level_1'], axis=1)
  21. dataframe.index.name = None
  22. returns = qb.History(symbols, start_time, end_time, Resolution.Daily)
  23. returns = returns.drop_duplicates().close.unstack(level=0)
  24. returns = returns.iloc[0] / returns.iloc[-1]
  25. #concat can also be used perfectly. dataframe = pd.concat([dataframe, returns), axis=1)
  26. dataframe['returns'] = returns
+ Expand

Where dataframe is a nice and clean dataframe with no issues. 

The code for the backtest is as follows, but not producing a nice dataframe like research.

  1. securities = [x for x in symbols]
  2. #our fundamental values
  3. fundamentals = ["ValuationRatios.SustainableGrowthRate", "ValuationRatios.PayoutRatio", "ValuationRatios.CashReturn", "ValuationRatios.FCFRatio", "ValuationRatios.EarningYield", "ValuationRatios.SalesYield", "ValuationRatios.BookValueYield", "ValuationRatios.PBRatio",
  4. "ValuationRatios.PEGRatio", "ValuationRatios.BuyBackYield", "ValuationRatios.PricetoEBITDA", "ValuationRatios.ForwardPERatio", "ValuationRatios.EVToEBITDA3YrAvgChange",
  5. "ValuationRatios.EVtoFCF", "ValuationRatios.EVtoEBIT", "ValuationRatios.EVToForwardEBITDA", "ValuationRatios.EVToForwardRevenue", "ValuationRatios.ForwardROE",
  6. "ValuationRatios.ForwardDividend"]
  7. #setting empty dataframe that we can concat with
  8. dataframe = pd.DataFrame()
  9. #Get the returns of the stocks, and get them shaped proberly
  10. dataframe = algorithm.History([x.Symbol for x in securities], returnLookback, Resolution.Daily)
  11. dataframe = dataframe.drop_duplicates().close.unstack(level=0)
  12. dataframe = dataframe.iloc[0] / dataframe.iloc[-1]
  13. dataframe = pd.DataFrame(dataframe)
  14. dataframe = dataframe.rename(columns={0: 'returns'})
  15. fundamental_dataframe = pd.DataFrame()
  16. #we need to get the symbols and symbol object, so we can set the name in the dataframe, and also get the fundamental value (ticker = setting name)
  17. for fundamental in securities:
  18. ratio = [fundamental.ValuationRatios.SustainableGrowthRate,
  19. fundamental.ValuationRatios.PayoutRatio,
  20. fundamental.ValuationRatios.CashReturn,
  21. fundamental.ValuationRatios.FCFRatio,
  22. fundamental.ValuationRatios.EarningYield,
  23. fundamental.ValuationRatios.SalesYield,
  24. fundamental.ValuationRatios.BookValueYield,
  25. fundamental.ValuationRatios.PEGRatio,
  26. fundamental.ValuationRatios.PBRatio,
  27. fundamental.ValuationRatios.BuyBackYield,
  28. fundamental.ValuationRatios.PricetoEBITDA,
  29. fundamental.ValuationRatios.ForwardPERatio,
  30. fundamental.ValuationRatios.EVToEBITDA3YrAvgChange,
  31. fundamental.ValuationRatios.EVtoFCF,
  32. fundamental.ValuationRatios.EVtoEBIT,
  33. fundamental.ValuationRatios.EVToForwardEBITDA,
  34. fundamental.ValuationRatios.EVToForwardRevenue,
  35. fundamental.ValuationRatios.ForwardROE,
  36. fundamental.ValuationRatios.ForwardDividend]
  37. #transpose the dataframe, so it is a long dataframe like in the notebook, set the column names, and concat
  38. ratio = pd.DataFrame(ratio, index = fundamentals, columns=[fundamental.Symbol])
  39. ratio = ratio.transpose()
  40. fundamental_dataframe = pd.concat([ratio, fundamental_dataframe], axis=0)
  41. #Make the dataframe into a nicely shaped dataframe
  42. #Append the 2 dataframes
  43. dataframe = pd.concat([fundamental_dataframe, dataframe], axis=1)
+ Expand

I have tried the following:

  • Appending fundamental data does not work -- makes a copy, and does not merge/concat
  • Making 2 dataframes and merging/concat does not work, half of the new dataframe is Nan
  • Making 1 dataframe with fundamental, and one series, making a new column with the seriesdoes not work either. Returns column is Nan


Anyone have a fix, or something that could solve the problem described above?

Have a good day

Lucas

Author

Lucas

April 2022