@rajanprabu said in Multi-Timeframe works for compression=15 but fails for 16:
params = (('period', 16),) def __init__(self): self.addminperiod(self.params.period)
Worked like a charm...
Thank you very much @rajanprabu
@rajanprabu said in Multi-Timeframe works for compression=15 but fails for 16:
params = (('period', 16),) def __init__(self): self.addminperiod(self.params.period)
Worked like a charm...
Thank you very much @rajanprabu
Datafeed: feed.csv [0_1610445720484_feed.csv](Uploading 100%)
Original timeframe of the feed is 1 minute
Objective:
from backtrader import Strategy
from backtrader import Indicator
import pandas as pd
class Dummy(Indicator):
lines = ('l',)
def next(self):
# Datetime of the latest completed bars in both Time-Frames
print(self.data0.datetime.datetime(0), end=": ")
print(self.data1.datetime.datetime(0))
class TestStrategy(Strategy):
params = ()
def __init__(self):
# Initializing dummy indicator (defined above)
self.d = Dummy(self.data0, self.data1)
pass
def next(self):
# Datetime of the latest completed bars in both Time-Frames
print(self.data0.datetime.datetime(0), end=": ")
print(self.data1.datetime.datetime(0))
df = pd.read_csv('feed.csv',
index_col='timestamp',
parse_dates=True)
data = bt.feeds.PandasData(
dataname=df,
openinterest='oi',
timeframe=bt.TimeFrame.Minutes,
compression=1,
sessionstart=sessionstart,
sessionend=sessionend
)
# Creating the Cerebro instance
cerebro = bt.Cerebro(runonce=False)
# Adding Strategy: TestStrategy (defined above)
cerebro.addstrategy(TestStrategy)
# Adding feed 1 -> `1 minute` data. Smaller Time-Frame First
cerebro.adddata(data)
# Adding feed 2 -> Resampling `1 minute' to `15 minute`
cerebro.resampledata(data,
timeframe=bt.TimeFrame.Minutes,
compression=15)
# Executing
cerebro.run(stdstats=False)
cerebro.plot(style='candle', barup='green')
Output using compression 15:
2020-01-01 09:15:00: 2020-01-01 09:15:00
2020-01-01 09:15:00: 2020-01-01 09:15:00
2020-01-01 09:16:00: 2020-01-01 09:15:00
2020-01-01 09:16:00: 2020-01-01 09:15:00
2020-01-01 09:17:00: 2020-01-01 09:15:00
2020-01-01 09:17:00: 2020-01-01 09:15:00
2020-01-01 09:18:00: 2020-01-01 09:15:00
2020-01-01 09:18:00: 2020-01-01 09:15:00
2020-01-01 09:19:00: 2020-01-01 09:15:00
2020-01-01 09:19:00: 2020-01-01 09:15:00
2020-01-01 09:20:00: 2020-01-01 09:15:00
2020-01-01 09:20:00: 2020-01-01 09:15:00
2020-01-01 09:21:00: 2020-01-01 09:15:00
2020-01-01 09:21:00: 2020-01-01 09:15:00
2020-01-01 09:22:00: 2020-01-01 09:15:00
But when the compression is changed to 16, execution throws Index Error
# Adding feed 2 -> Resampling `1 minute' to `15 minute`
cerebro.resampledata(data,
timeframe=bt.TimeFrame.Minutes,
compression=16)
Output using compression 16:
File "C:\Users\PC2\PycharmProjects\Backtrader\venv\lib\site-packages\backtrader\lineiterator.py", line 347, in nextstart
self.next()
File "C:/Users/PC2/.PyCharmCE2019.1/config/scratches/Test.py", line 10, in next
print(self.data1.datetime.datetime(0))
File "C:\Users\PC2\PycharmProjects\Backtrader\venv\lib\site-packages\backtrader\linebuffer.py", line 387, in datetime
return num2date(self.array[self.idx + ago],
IndexError: array index out of range
Problem: Multi-Timeframe works well with compression=15 but fails with compression=16 (or any other than 15)
Observation:
self.data1.datetime.datetime(0)
works well for all Time-Frames in the next
method of Strategy
. But throws Index Error
for Time-Frames other than 15 in the next
method of Indicator
I'd be really grateful if someone can help me understand where am I going wrong.
try to add sessionstart and sessionend parameters. seems logical to have them.
It worked. Can't thank you enough @ab_trader
pandas
will just help resample the minute data to a higher timeframe. Am I right?Hello, I've tried replaying data containing one minute bars. But there's something I'm missing. I've used the example given in the docs. It works well for destination timeframe weekly
but fails for daily
and intraday.
Here is a brief explanation of what I've done.
Please have a look into it.
Thank you in advance:)
@Tom-Porter said in typo found in indicators documentation.:
class MyStrategy(bt.Strategy):
def __init__(self):
sma1 = btind.SimpleMovingAverage(self.data)
ema1 = btind.ExponentialMovingAverage()
close_over_sma = self.data.close > sma1
close_over_ema = self.data.close > ema1
sma_ema_diff = sma1 - ema1
self.buy_sig = bt.And(...)
def next(self):
if self.buy_sig:
self.buy()
Absolutely. Thanks for pointing it out Tom.
@Carson-Lansdowne said in Accessing variable defined in strategy from main Cerebro:
Hey Carson,
def stop(self):
global roi
# calculate the actual returns
print(self.value)
roi = ((self.broker.get_value() -self.val_start) / (self.value))
print('ROI: {:.2f}%'.format(100.0 * self.roi))
#return self.roi
This snippet is copied from your code as it was.
You have defined a new variable global roi
but you are trying to access it as a class attribute
. Try using roi
instead of self.roi
in the print statement of your method. Hope it works. :)
Hey Carson,
I guess you are confused between sizer
and size
.
sizer
is a python class that comes with the backtrader module.
size
is the quantity that you want to buy during a specific self.buy()
call.
In order to derive the size to be bought logically, you must create a sub class that inherits from bt.Sizer
base class.
import backtrader as bt
class FixedSize(bt.Sizer):
params = (('stake', 1),)
def _getsizing(self, comminfo, cash, data, isbuy):
return self.params.stake
something like this...
More on bt.Sizers
available here.
@rajanprabu said in Compression using daily and minute timeframes unsuccessful during replaydata():
te timefr
I tried it with the additional param compression=1
but the result is still the same.
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import argparse
import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind
from datetime import datetime
class SMAStrategy(bt.Strategy):
params = (
('period', 10),
('onlydaily', False),
)
def __init__(self):
pass
def start(self):
self.counter = 0
def prenext(self):
self.counter += 1
print(f'{self.datas[0].datetime.datetime(0)} prenext len %d - counter %d' % (len(self), self.counter))
def next(self):
self.counter += 1
print(f'{self.datas[0].datetime.datetime(0)} ---next len %d - counter %d' % (len(self), self.counter))
def runstrat():
args = parse_args()
# Create a cerebro entity
cerebro = bt.Cerebro(stdstats=False)
cerebro.addstrategy(
SMAStrategy,
# args for the strategy
period=args.period,
)
# Load the Data
datapath = args.dataname or "nifty19-20.csv"
data = btfeeds.BacktraderCSVData(dataname=datapath, fromdate=datetime.now().replace(year=2020, month=8, day=17, hour=0, minute=0, second=0), timeframe=bt.TimeFrame.Minutes, compression=1)
# Handy dictionary for the argument timeframe conversion
tframes = dict(
minute=bt.TimeFrame.Minutes,
daily=bt.TimeFrame.Days,
weekly=bt.TimeFrame.Weeks,
monthly=bt.TimeFrame.Months)
# First add the original data - smaller timeframe
cerebro.replaydata(data,
timeframe=tframes['daily'],
compression=1)
# Run over everything
cerebro.run()
# Plot the result
cerebro.plot(style='bar')
def parse_args():
parser = argparse.ArgumentParser(
description='Pandas test script')
parser.add_argument('--dataname', default='', required=False,
help='File Data to Load')
parser.add_argument('--timeframe', default='minute', required=False,
choices=['minute', 'daily', 'weekly', 'monhtly'],
help='Timeframe to resample to')
parser.add_argument('--compression', default=10, required=False, type=int,
help='Compress n bars into 1')
parser.add_argument('--period', default=10, required=False, type=int,
help='Period to apply to indicator')
return parser.parse_args()
if __name__ == '__main__':
runstrat()
2020-08-20 23:59:59.999989 ---next len 1482 - counter 1482
2020-08-20 23:59:59.999989 ---next len 1483 - counter 1483
2020-08-20 23:59:59.999989 ---next len 1484 - counter 1484
2020-08-20 23:59:59.999989 ---next len 1485 - counter 1485
2020-08-20 23:59:59.999989 ---next len 1486 - counter 1486
2020-08-20 23:59:59.999989 ---next len 1487 - counter 1487
2020-08-20 23:59:59.999989 ---next len 1488 - counter 1488
2020-08-20 23:59:59.999989 ---next len 1489 - counter 1489
2020-08-20 23:59:59.999989 ---next len 1490 - counter 1490
2020-08-20 23:59:59.999989 ---next len 1491 - counter 1491
2020-08-20 23:59:59.999989 ---next len 1492 - counter 1492
2020-08-20 23:59:59.999989 ---next len 1493 - counter 1493
2020-08-20 23:59:59.999989 ---next len 1494 - counter 1494
2020-08-20 23:59:59.999989 ---next len 1495 - counter 1495
2020-08-20 23:59:59.999989 ---next len 1496 - counter 1496
2020-08-20 23:59:59.999989 ---next len 1497 - counter 1497
2020-08-20 23:59:59.999989 ---next len 1498 - counter 1498
2020-08-20 23:59:59.999989 ---next len 1499 - counter 1499
2020-08-20 23:59:59.999989 ---next len 1500 - counter 1500
:(
I still can;t figure out where exactly am I going wrong!
Btw, Thanks Rajan for the help.
@Carson-Lansdowne said in Attribute Error: object has no attribute 'postion':
postion
Hey Carson.
A little modification in the 31st line of your code is required.
Under the class method next
within the class buynhold_1
, make the following changes:
Old code:
if not self.postion:
if self.currdate == datetime.date(2016, 1, 3):
self.buy()
self.bar_executed = len(self)
New Code:
if not self.position:
if self.currdate == datetime.date(2016, 1, 3):
self.buy()
self.bar_executed = len(self)
It's a mere spelling error self.position
and not self.postion
. Hope it works now:)