@Z also just noticed that the very first file of my SP500 folder doesn't have data until 1999-11-18. Undoubtedly the issue has something to do with this. I will look again tomorrow, but if anybody has the solution in the meantime I would appreciate it!
Latest posts made by Z
-
RE: self.data.datetime.date() starting at the last date of my data
-
self.data.datetime.date() starting at the last date of my data
Hello,
I am having an issue where my strategy starts off at the very end of my data, but then goes back to normal after a while and starts from the beginning and goes to the end just fine. I put a print statement at the beginning of the "next" method of the strategy class that prints out self.data.datetime.date() and it prints out 2022-12-30 (which is the very last day of my data) a bunch of times. Then it proceeds to print dates from 1999-11-18 until 2022-12-30 as normal. Keep in mind that my data starts at 1998-01-03 ... NOT 1999-11-18.
Here is the code for the strategy script:
import backtrader as bt import backtrader.indicators as btind import pandas as pd class MovingAverageCrossover(bt.Strategy): params = ( ('ma_short_length', 50), ('ma_long_length', 200), ) def __init__(self): self.ma_short_dict = {} self.ma_long_dict = {} for data in self.datas: if self.has_sufficient_data(data): self.ma_short_dict[data] = btind.ExponentialMovingAverage(data.close, period=self.params.ma_short_length) self.ma_long_dict[data] = btind.ExponentialMovingAverage(data.close, period=self.params.ma_long_length) def prenext(self): self.next() def next(self): print(self.data.datetime.date()) for data in self.datas: if data in self.ma_short_dict and data in self.ma_long_dict: ma_short = self.ma_short_dict[data] ma_long = self.ma_long_dict[data] if ma_short[0] > ma_long[0] and ma_short[-1] <= ma_long[-1]: self.buy(data=data, size=1) elif ma_short[0] < ma_long[0] and ma_short[-1] >= ma_long[-1]: self.close(data=data, size=1) def has_sufficient_data(self, data): df = pd.read_csv(fr'C:\Users\Z\Desktop\Python\Backtest\Backtrader Stock Data\SP500\
Any ideas?
Thanks,
Zack -
Error Calculating EMA
Hello,
I have an issue when calculating the EMA for all my stocks, but not when only calculating some. Here is the code:
class MovingAverageCrossover(bt.Strategy): params = ( ('ma_short_length', 50), ('ma_long_length', 200), ) def __init__(self): for data in self.datas: data.ma_short = btind.ExponentialMovingAverage(data.close, period=self.params.ma_short_length) data.ma_long = btind.ExponentialMovingAverage(data.close, period=self.params.ma_long_length)
The error is occurring during cerebro.run, but it is related to the EMA... Here is the error:
Traceback (most recent call last): File "c:\Users\Z\Desktop\Python\Backtest\main.py", line 15, in <module> results = cerebro.run() ^^^^^^^^^^^^^ File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\cerebro.py", line 1132, in run runstrat = self.runstrategies(iterstrat) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\cerebro.py", line 1298, in runstrategies self._runonce(runstrats) File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\cerebro.py", line 1657, in _runonce strat._once() File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\lineiterator.py", line 297, in _once indicator._once() File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\lineiterator.py", line 297, in _once indicator._once() File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\lineiterator.py", line 317, in _once self.oncestart(self._minperiod - 1, self._minperiod) File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\indicators\basicops.py", line 401, in oncestart super(ExponentialSmoothing, self).once(start, end) File "C:\Users\Z\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\indicators\basicops.py", line 364, in once dst[i] = math.fsum(src[i - period + 1:i + 1]) / period ~~~^^^ IndexError: array assignment index out of range
We get through the init method, but never get the prenext or next methods. I am clueless. Thanks for any help!
-
Calculating Indicators for Multiple Assets
Hello,
I am trying to calculate indicators for multiple assets. So, if I had 3 stocks AAPL, GOOG, and FB, I would want each of them to have a Short MA and a Long MA associated with them. Here is my current code for my strategy:
class MovingAverageCrossover(bt.Strategy): params = ( ('ma_short_length', 50), ('ma_long_length', 200), ) def __init__(self): self.ma_short = btind.ExponentialMovingAverage(self.data.close, period=self.params.ma_short_length) self.ma_long = btind.ExponentialMovingAverage(self.data.close, period=self.params.ma_long_length) def next(self): for data in self.datas: print(f"Stock: {data._name} Close: {round(data.close[0], 2)}")
Within the "next" method, I am currently just printing the close for each stock along with it's name. I would like to be able to print the ma_short and ma_long values instead.
Basically just trying to figure out how to assign and access indicator values for multiple assets! Not sure where I'm going wrong, but I'm sure it's pretty simple.
Thanks for the help!
-
RE: does RSI work?
@jbxxs I am not certain that this will fix it, but it does seem as if you are using "rsi_low" and "rsi_high" which are not attributes of the RSI Indicator Object. From the documentation:
*RelativeStrengthIndex
Formula:
up = upday(data)
down = downday(data)
maup = movingaverage(up, period)
madown = movingaverage(down, period)
rs = maup / madown
rsi = 100 - 100 / (1 + rs)The moving average used is the one originally defined by Wilder, the SmoothedMovingAverage
safediv (default: False) If this parameter is True the division rs = maup / madown will be checked for the special cases in which a 0 / 0 or x / 0 division will happen
safehigh (default: 100.0) will be used as RSI value for the x / 0 case
safelow (default: 50.0) will be used as RSI value for the 0 / 0 caseLines:
rsi
Params:
period (14)
movav (SmoothedMovingAverage)
upperband (70.0)
lowerband (30.0)
safediv (False)
safehigh (100.0)
safelow (50.0)
lookback (1)*Can you please try using the attributes "upperband" and "lowerband" instead? Note: You do not need to specify the values to be 70 and 30 since those are the default values. You also do not need to specify the period to be 14.
Try printing the "upperband" value to ensure you are accessing it correctly. Please let me know if this works! -
Data Structure for Holding Metrics
I am having a hard time coming up with a data structure that can hold metrics in a nice clean way. I might be a little slow and am just overthinking it, but either way figured asking here might help me get some clarification or some valuable insight into how to approach a problem like this.
So, I would like to have a data structure that can hold metrics based on what I call "Data Scope" as well as what I call "Data Slice". Data Scope is just what I use to refer to the size of the data (whole portfolio, stock sector, individual stock). Data Slice is just what I use to refer to the time period of the data (whole period, yearly, monthly).
The thing I am having a tough time wrapping my head around is how I can create an overall data structure that I can organize without giving Data Scope or Data Slice larger importance. For example, if Overall Data Structure> Data Slice > Data Scope, then I can look at the year 2019 for the stock AAPL. But, what if now I don't care about the Data Slice (time period)? What if I just want to look at everything relating to AAPL? Data Scope isn't the larger structure so I have to access all the AAPL info through different time periods.
As I said, I might be overcomplicating things (I probably am), but I would enjoy a solution as well as an explanation of where I am going wrong with my thinking.
Thanks Much!
Z -
RE: Newbie dtformat
@tavagnascoi here is my code:
data = btfeeds.GenericCSVData( dataname=file_path, nullvalue=0.0, dtformat=('%Y-%m-%d'), datetime=0, open=1, high=2, low=3, close=4, volume=5, openinterest=-1 )
Seems like you need to put the dtformat's value in parentheses? Let me know if that fixes it. I am a newbie as well.
-
Check Portfolio Value Before Trading
Hello,
I would like to be able to store my portfolio value in a variable before I make any trades on a given day. I know how to do this for the whole of the Cerebro run period, but not how to do it in the middle of a run. Basically I want to track the returns for a month. So, on January 1st 1999 I want to check my portfolio value BEFORE trading... then on January 29th 1999 (last day of January) I want to check my portfolio value AFTER trading.
I can definitely just use the After-Trading value of the previous day, and I will if need be. I'm just curious if there's a way to do it in the way I described.
Thanks!
-
RE: how to buy at current day close price?
You just need to set your Broker Object's "coc" value to True. It allows you to cheat-on-close (basically you can sell at the closing price even though the day is technically over).
From the documentation:
coc (default: False)
Cheat-On-Close Setting this to True with set_coc enables
matching a
Market
order to the closing price of the bar in which
the order was issued. This is actually cheating, because the bar
is closed and any order should first be matched against the prices
in the next barJust add this line after your Broker has been instantiated: cerebro.broker.set_coc(True)
-
RE: How to extract date stamp from YfinanceData
@Chandrahas-Patel no problem! I found the information in the documentation. It might also be useful for you to know that you can access the actual time of the date using self.data.datetime.time() (Formatted as such: 23:59:59.999989). Similarly, you can access both at the same time using self.data.datetime.datetime() (Formatted as such: 2022-12-30 23:59:59.999989).
Glad to be able to help!