How to do with self.broker.getvalue() which return NAN when do portfolio with different public date?
-
when i run a portfolio strategy, the stocks have different public date, so I fill data with method ffill in python fillna, when i run the strategy, I find that i could not order buy or sell because when i get portfolio value by self.broker.getvalue which is NAN, i could not calculate the order size……help me, how to cope with it ?
the error is :
Traceback (most recent call last):
File "Z:/QEPM_BackTest/src/dev/Backtest/single_factor_backtrade.py", line 360, in <module>
run()
File "Z:/QEPM_BackTest/src/dev/Backtest/single_factor_backtrade.py", line 345, in run
thestrats = cerebro.run()
File "D:\Anaconda\lib\site-packages\backtrader\cerebro.py", line 1127, in run
runstrat = self.runstrategies(iterstrat)
File "D:\Anaconda\lib\site-packages\backtrader\cerebro.py", line 1293, in runstrategies
self._runonce(runstrats)
File "D:\Anaconda\lib\site-packages\backtrader\cerebro.py", line 1695, in _runonce
strat._oncepost(dt0)
File "D:\Anaconda\lib\site-packages\backtrader\strategy.py", line 309, in _oncepost
self.next()
File "Z:/QEPM_BackTest/src/dev/Backtest/single_factor_backtrade.py", line 249, in next
self.rebalance_portfolio()
File "Z:/QEPM_BackTest/src/dev/Backtest/single_factor_backtrade.py", line 284, in rebalance_portfolio
size = int(p_value / 100 / data.close[0]) * 100
ValueError: cannot convert float NaN to integerthe following is my code:
class S_factors(bt.Strategy):
params = dict(
period=20,
printlog=True, )def __init__(self): print("\n" + "*" * 30 + " Start trading " + "*" * 30) self.order = None def log(self, txt, dt=None, doprint=True): if self.params.printlog or doprint: dt = dt or self.datetime.date(0) print(f'{dt.isoformat()} {txt}') def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: return if order.status in [order.Completed]: if order.isbuy(): self.log(f'{self.broker.cash} {self.broker.getvalue()}') else: sself.log(f'{self.broker.cash} {self.broker.getvalue()}') elif order.status in [order.Canceled]: self.log(f'{self.broker.cash} {self.broker.getvalue()}') elif order.status in [order.Margin]: self.log(f'{self.broker.cash} {self.broker.getvalue()}') elif order.status in [order.Rejected]: self.log(f'{self.broker.cash} {self.broker.getvalue()}') self.order = None def prenext(self): self.next() def next(self): self.broker.getcash()) if len(self.datas[0]) == self.data0.buflen(): return if self.datas[0].is_resetday[0] == 1 \ and datetime.strptime(str(self.datetime.date(0)), "%Y-%m-%d") > datetime.strptime("2014-03-17", "%Y-%m-%d"): # print("resetday---->>>>>") self.rebalance_portfolio() def rebalance_portfolio(self): factor_vl = pd.Series() for data in self.datas: if not pd.isnull(data.close[0]) and data.industry[0] == self.p.selected_ind and not pd.isnull(data.factor[0]): factor_vl[data._name] = data.factor[0] factor_vl.sort_values(ascending=False, inplace=True) layer_num = int(len(factor_vl) / self.p.layer_N) layer_num = max(layer_num, self.p.min_num_stk) long_list = [i for i in factor_vl.index[:layer_num]] for o in long_list: self.cancel(o) if len(long_list)==0: return total_value = self.broker.getvalue() p_value = total_value * 0.8 / layer_num self.datas.sort(key=lambda d: self.broker.getvalue([d]), reverse=True) for d in self.datas: print(data._name, self.broker.getvalue([d])) for data in self.datas: if data._name in long_list: size = int(p_value / 100 / data.close[0]) * 100 # print(self.datetime.date(0), self.broker.getvalue(), self.broker.getcash()) # print("OHLC:", data.open[0], data.high[0], data.low[0], data.close[0]) self.order_target_size(data=data, target=size) else: self.close(data=data, exectype=bt.Order.Close)