Hi all,
Is there a way to return a dataframe from a custom indictor?
For context I have checked the code, all is working, I can print the DF within the custom indicator and the values are populating the dataframe, but I'm having trouble returning it. I need to be able to return it so I can see the visual output without it printing for each tradebar…
I've been using “custom = customindicator()” and nothing prints.
I do not know how to use a rollingwindow to capture dataframe values, if that's how this needs to be done.
I'm using local platform (quantbook).
# QuantBook Analysis Tool
# For more information see https://www.quantconnect.com/docs/research/overview
#Required QuantConnect Imports
from AlgorithmImports import *
from collections import deque
#Supplementary Imports
import plotly.graph_objects as go
import pandas as pd
import numpy as np
import statistics as st
import math
#Quantbook data pulling
qb = QuantBook()
symbol = qb.add_equity('TSLA').symbol
history = qb.history[TradeBar](symbol, 500, Resolution.DAILY)
data_df = qb.PandasConverter.GetDataFrame[TradeBar](history)
print(history)
print(data_df)
## START SUPPLEMENTARY FUNCTIONS --------------------------------------------------------------------------------------------------
def nz(x, y=None):
'''
RETURNS
Two args version: returns x if it's a valid (not NaN) number, otherwise y
One arg version: returns x if it's a valid (not NaN) number, otherwise 0
ARGUMENTS
x (val) Series of values to process.
y (float) Value that will be inserted instead of all NaN values in x series.
'''
if isinstance(x, np.generic):
return x.fillna(y or 0)
if x != x:
if y is not None:
return y
return 0
return x
def wwma(values, n):
"""
J. Welles Wilder's EMA
"""
return values.ewm(alpha=1/n, adjust=False).mean()
def rma(s: pd.Series, period: int) -> pd.Series:
return s.ewm(alpha=1 / period).mean()
def crossover_series(x: pd.Series, y: pd.Series, cross_distance: int = None) -> pd.Series:
shift_value = 1 if not cross_distance else cross_distance
return (x > y) & (x.shift(shift_value) < y.shift(shift_value))
def crossunder_series(x: pd.Series, y: pd.Series, cross_distance: int = None) -> pd.Series:
shift_value = 1 if not cross_distance else cross_distance
return (x < y) & (x.shift(shift_value) > y.shift(shift_value))
## END SUPPLEMENTARY FUNCTIONS --------------------------------------------------------------------------------------------------
## START ATR FUNCTIONS --------------------------------------------------------------------------------------------------
def ATR_8(data: pd.DataFrame, window=14, use_nan=True) -> pd.Series:
df_ = data.copy(deep=True)
window_1 = 50
window_2 = 10
df_.loc[:, 'H_L'] = df_['high'] - df_['low']
df_.loc[:, 'H_Cp'] = abs(df_['high'] - df_['close'].shift(1))
df_.loc[:, 'L_Cp'] = abs(df_['low'] - df_['close'].shift(1))
df_.loc[:, 'TR'] = df_[["H_L", "H_Cp", "L_Cp"]].max(axis=1)
df_.loc[:, 'ATR_1'] = df_['TR'].rolling(window_1).mean()*3.5
df_.loc[:, 'ATR_2'] = df_['TR'].rolling(window_2).mean()*3.5
df_.loc[:, 'ATR'] = (df_['ATR_1'] + df_['ATR_2']) / 2
df_.loc[:, 'up'] = df_['ATR']+((df_['high'] + df_['low'] + df_['close'])/3)
df_.loc[:, 'dn'] = ((df_['high'] + df_['low'] + df_['close'])/3)-df_['ATR']
for i in range(window, len(df_)):
df_.iloc[i, df_.columns.get_loc('ATR')] = (((df_.iloc[i - 1, df_.columns.get_loc('ATR')]) * (window - 1)) + df_.iloc[
i, df_.columns.get_loc('TR')]) / window
df_['upper'] = df_['close']
df_['lower'] = df_['close']
df_['upper_last'] = 0.0
df_['lower_last'] = 0.0
df_['upper_last'] = df_['upper'].shift(-1)
df_['lower_last'] = df_['lower'].shift(-1)
df_.loc[(df_['close'].shift(-1) < df_['upper'].shift(-1)), 'upper'] = df_['up']
df_.loc[(df_['close'].shift(-1) > df_['upper'].shift(-1)), 'upper'] = df_[['up','upper_last']].min(axis=1)
df_.loc[(df_['close'].shift(-1) < df_['lower'].shift(-1)), 'lower'] = df_['dn']
df_.loc[(df_['close'].shift(-1) > df_['lower'].shift(-1)), 'lower'] = df_[['dn','lower_last']].max(axis=1)
df_['os'] = 0.0
df_.loc[(df_['close'] > df_['upper']), 'os'] = 1.0
df_.loc[(df_['close'] < df_['lower']), 'os'] = 0.0
df_.loc[((df_['close'] <= df_['upper']) & (df_['close'] >= df_['lower'])), 'os'] = df_['os'].shift(-1)
df_['spt'] = 0.0
df_.loc[(df_['os'] == 1.0), 'spt'] = df_['lower']
df_.loc[(df_['os'] != 1.0), 'spt'] = df_['upper']
df_['max'] = 0.0
df_['min'] = 0.0
df_['max_last'] = df_['max'].shift(-1)
df_['min_last'] = df_['min'].shift(-1)
df_.loc[((df_['os'] == 0.0) | ((df_['spt'].shift(-1) <= df_['close'].shift(-1)) & (df_['spt'] > df_['close']))), 'max'] = df_[['spt','max_last']].min(axis=1)
df_.loc[((df_['os'] == 1.0) | ((df_['spt'].shift(-1) >= df_['close'].shift(-1)) & (df_['spt'] < df_['close']))), 'min'] = df_[['spt','min_last']].max(axis=1)
df_.loc[(df_['os'] == 1.0), 'max'] = df_[['close','max_last']].max(axis=1)
df_.loc[(df_['os'] == 0.0), 'min'] = df_[['close','min_last']].min(axis=1)
df_.loc[((df_['spt'].shift(-1) >= df_['close'].shift(-1)) & (df_['spt'] < df_['close'])), 'max'] = df_[['close','max_last']].max(axis=1)
df_.loc[((df_['spt'].shift(-1) <= df_['close'].shift(-1)) & (df_['spt'] > df_['close'])), 'min'] = df_[['close','min_last']].min(axis=1)
df_['avg'] = df_[['max','min']].min(axis=1)
#end new addition
if use_nan:
df_.iloc[:window, df_.columns.get_loc('ATR')] = np.nan
return df_#['ATR']
## END ATR FUNCTIONS --------------------------------------------------------------------------------------------------
## Start Indicator Class --------------------------------------------------------------------------------------------------
class MYATR(PythonIndicator):
def __init__(self, baselength, mult, data_df):
self.mrma_value = None # Attribute represents the indicator value
self.value_at_risk = None
self.deviation = None
self.mult = mult
self.baselength = baselength # renamed from alpha
self.std = StandardDeviation(baselength)
self.window_renamed = RollingWindow[float](baselength)
self.data_df = data_df
self.max = 0.0
self.avg = 0.0
self.min = 0.0
# Override the IsReady attribute to flag all attributes values are ready.
@property
def is_ready(self) -> bool:
return self.mult
# all of the accessing OHLC will go here
# Method to update the indicator values. Note that it only receives 1 IBaseData object (Tick, TradeBar, QuoteBar) argument.
def Update(self, input: BaseData) -> bool:
count = self.window_renamed.Count
self.window_renamed.Add(input.Close)
# Update the Value and other attributes as the indicator current value.
if count >= 10:
## Handle OHLC
self.open = input.Open
self.high = input.High
self.low = input.Low
self.close = input.Close
## Calculate the volatility as a percentage of the price ------------------------------------------------------------------------------
self.testlist = list(self.window_renamed)[::-1]
self.data_df = data_df
self.data_top = self.data_df.head()
##------------------------------------------------------------------------------
self.hlc3 = (self.high+self.low+self.close)/3
self.length = self.baselength
self.mult = self.mult
self.upper = 0.0
self.lower = 0.0
self.os = 0.0
self.max = 0.0
self.min = 0.0
self.src = self.close
##------------------------------------------------------------------------------
self.full_atr = ATR_8(self.data_df, self.length, True)
print(self.full_atr)
#Python dequeuing
self.queue = deque(maxlen=self.baselength)
print('queue finished')
# return a boolean to indicate IsReady.
print('count finished')
return self.full_atr if count >= 10 else False
## END Indicator Class --------------------------------------------------------------------------------------------------
## START Run Indicator and Instantiate Windows --------------------------------------------------------------------------------------------------
custom = MYATR(50, 3.5, data_df)
print(custom)
#tinkle
window = {}
window['dataframe'] = RollingWindow[pd.DataFrame](92)
## END Run Indicator and Instantiate Windows --------------------------------------------------------------------------------------------------
## START Pull Data and Route Data --------------------------------------------------------------------------------------------------
for bar in history:
custom.Update(bar)
print(custom)
# The Updated event handler is not available for custom indicator in Python, RollingWindows are needed to be updated in here.
#tinkle
if custom.is_ready:
print(custom)
window['dataframe'].add(custom.full_atr)
custom_dataframe = pd.DataFrame(window).set_index('time')
print(custom_dataframe)
print('end custom dataframe')
The code below “# START Run Indicator and Instantiate Windows….” is where I'm having issues.
Warm regards,
Kevin
Kevin VanHelden
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!