Backtrader issue - optstrategy AttributeError: module 'collections' has no attribute 'Iterable' - python

I'm trying to optimize my strategy on Backtrader with python but keeps getting this error and i can't find anything on the web showing why I'm getting it.
My code is simple and loosely based on the quick start examples:
from alpaca_trade_api.rest import REST, TimeFrame, TimeFrameUnit
import backtrader as bt
from config import API_KEY, SECRET_KEY
class EMACross(bt.Strategy):
params = dict(
ema_short_period=5,
ema_long_period=10
)
def __init__(self):
self.order = None
self.short_ma = bt.indicators.ExponentialMovingAverage(period=self.p.ema_short_period)
self.long_ma = bt.indicators.ExponentialMovingAverage(period=self.p.ema_long_period)
self.crossover = bt.ind.CrossOver(self.short_ma, self.long_ma) # crossover signal
self.crossdown = bt.ind.CrossDown(self.short_ma, self.long_ma)
self.crossdown.plotinfo.subplot = False
self.crossover.plotinfo.subplot = False
def next(self):
self.log('Close, %.2f' % self.data.close[0])
if self.position.size > 0:
if self.crossdown > 0:
self.log('SELL CREATE, %.2f' % self.data.close[0])
self.close()
else:
if self.crossover > 0:
self.log('BUY CREATE, %.2f' % self.data.close[0])
self.buy()
def log(self, txt, dt=None):
dt = dt or self.data.datetime.datetime()
print('%s, %s' % (dt.isoformat(), txt))
def stop(self):
self.log('(short EMA Period %2d) (long EMA Period %2d) Ending Value %.2f' %
(self.p.ema_short_period, self.p.ema_long_period, self.broker.getvalue()))
rest_api = REST(API_KEY, SECRET_KEY, 'https://paper-api.alpaca.markets')
def run_backtest(strategy, symbols, start, end, timeframe, cash=100000):
# initialize backtrader broker
cerebro = bt.Cerebro()
cerebro.broker.setcash(cash)
cerebro.addsizer(bt.sizers.PercentSizer, percents=90)
cerebro.optstrategy(strategy, ema_short_period=4, ema_long_period=6)
# historical data request
if type(symbols) == str:
symbol = symbols
alpaca_data = rest_api.get_bars(symbol, timeframe, start, end, adjustment='all').df
data = bt.feeds.PandasData(dataname=alpaca_data, name=symbol)
cerebro.adddata(data)
elif type(symbols) == list or type(symbols) == set:
for symbol in symbols:
alpaca_data = rest_api.get_bars(symbol, timeframe, start, end, adjustment='all').df
data = bt.feeds.PandasData(dataname=alpaca_data, name=symbol)
cerebro.adddata(data)
# run
initial_portfolio_value = cerebro.broker.getvalue()
print(f'Starting Portfolio Value: {initial_portfolio_value}')
results = cerebro.run()
final_portfolio_value = cerebro.broker.getvalue()
print(
f'Final Portfolio Value: {final_portfolio_value} ---> Return: {(final_portfolio_value / initial_portfolio_value - 1) * 100}%')
run_backtest(EMACross, 'QQQ', '2018-01-01', '2022-01-01', TimeFrame(1, TimeFrameUnit.Day))
Running the script, i get this error:
Traceback (most recent call last):
File "/Users/usrname/PycharmProjects/test3/main.py", line 79, in <module>
run_backtest(EMACross, 'QQQ', '2018-01-01', '2022-01-01', TimeFrame(1, TimeFrameUnit.Day))
File "/Users/usrname/PycharmProjects/test3/main.py", line 54, in run_backtest
cerebro.optstrategy(strategy, ema_short_period=4, ema_long_period=6)
File "/Users/usrname/PycharmProjects/test3/venv/lib/python3.10/site-packages/backtrader/cerebro.py", line 893, in optstrategy
vals = self.iterize(kwargs.values())
File "/Users/usrname/PycharmProjects/test3/venv/lib/python3.10/site-packages/backtrader/cerebro.py", line 333, in iterize
elif not isinstance(elem, collections.Iterable):
AttributeError: module 'collections' has no attribute 'Iterable'
Process finished with exit code 1
When running the script without optstrategy() but rather with addstrategy(), evrything is working great. Only when changing to optstrategy is when i'm getting this error.
I also tried to run the same code on Google colab (with optstrategy() method) and everything worked great there, so this got me really puzzled...
I'm running python 3.10 with PyCharm CE on macOS.

Try downgrading from python 3.10 to python 3.8 version

Related

Invalid Argument when implementing sched

I've written a basic wrapper around sched.scheduler, but I'm getting:
File "/usr/local/anaconda3/lib/python3.7/sched.py", line 149, in run
delayfunc(time - now)
OSError: [Errno 22] Invalid argument
What is the cause of this error? I'm following https://docs.python.org/3/library/sched.html
Code:
#!/usr/local/anaconda3/bin/python
from time import time, sleep
from datetime import datetime, timezone
from sched import scheduler
class Scheduler:
# specify one or t'other e.g. "2021-03-17 02:29:00"
def __init__(self, event_time_utc:str='', local_unix_timestamp_override:float=0):
self.event_local_timestamp = Scheduler.to_local_unix_timestamp(event_time_utc) \
if event_time_utc else local_unix_timestamp_override
# self.seconds_until_event = event_local_timestamp - time()
print(self.event_local_timestamp - time())
self.sch = scheduler()
def run(self, blocking=False):
self.sch.run(blocking)
#staticmethod
def to_local_unix_timestamp(time_utc: str):
dt_utc = datetime.strptime(time_utc, "%Y-%m-%d %H:%M:%S")
dt_local = dt_utc.replace(tzinfo=timezone.utc)
return dt_local.timestamp()
#staticmethod
def to_human_readable(unix_timestamp):
return datetime.fromtimestamp(unix_timestamp).strftime('%Y-%m-%d %H:%M:%S.%f')
def schedule(self, offset_from_event_time_s:float, callback):
print('Event scheduled for local unix timestamp:', self.event_local_timestamp + offset_from_event_time_s)
self.sch.enterabs(
time = self.event_local_timestamp + offset_from_event_time_s,
priority = 1,
action = callback
)
if __name__ == '__main__':
sch = Scheduler(local_unix_timestamp_override=time()+5)
print(f'Started at time: {Scheduler.to_human_readable(time())}')
def callback():
print(f'Callback at time: {Scheduler.to_human_readable(time())}')
sch.schedule(offset_from_event_time_s=1, callback=callback)
sch.run(blocking=True)
Output:
> ./scheduler.py
4.999997854232788
Started at time: 2021-03-17 11:00:03.424191
f 1615953609.424139
Traceback (most recent call last):
File "./scheduler.py", line 55, in <module>
sch.run(blocking=True)
File "./scheduler.py", line 20, in run
self.sch.run(blocking)
File "/usr/local/anaconda3/lib/python3.7/sched.py", line 149, in run
delayfunc(time - now)
OSError: [Errno 22] Invalid argument
The root of the problem is that YOU are assuming that the sched module is using time.time() for its timing function. That is a false assumption. It is using time.monotonic() by default, which returns the time since your program started. That is going to be a small number, like 6. When you try to delay until 1615644884.1231558, that makes it go crazy.
Change this:
self.sch = scheduler()
to this:
self.sch = scheduler(time)
I tried debugging the issue and found that the max length of floating point value allowed in time.sleep() is 8 (I couldn't find any resource on why only 8) but since you are using timestamp the value exceeds that. You can try following code on your machine and check that:
import time
# Will work fine
time.sleep(16156448)
# Will result in error
time.sleep(1615644884.1231558)

Python Pandas Cannot import QUOTE_MINIMAL

I'm working on a library using pandas.
To develop the script of the library, I created a basic script that works as desired. Then, I copied this code in a .py file in the library folder and I always get the following error message when loading pandas:
Traceback (most recent call last):
File "D:/My/Path/Python Perfectionnement/analysis/csv.py", line 4, in <module>
import pandas as pd
File "C:\Users\Me\AppData\Local\Continuum\anaconda3\envs\pyperf\lib\site-packages\pandas\__init__.py", line 145, in <module>
from pandas.io.api import (
File "C:\Users\Me\AppData\Local\Continuum\anaconda3\envs\pyperf\lib\site-packages\pandas\io\api.py", line 8, in <module>
from pandas.io.excel import ExcelFile, ExcelWriter, read_excel
File "C:\Users\Me\AppData\Local\Continuum\anaconda3\envs\pyperf\lib\site-packages\pandas\io\excel\__init__.py", line 1, in <module>
from pandas.io.excel._base import ExcelFile, ExcelWriter, read_excel
File "C:\Users\Me\AppData\Local\Continuum\anaconda3\envs\pyperf\lib\site-packages\pandas\io\excel\_base.py", line 9, in <module>
from pandas._libs.parsers import STR_NA_VALUES
File "pandas\_libs\parsers.pyx", line 12, in init pandas._libs.parsers
ImportError: cannot import name QUOTE_MINIMAL
Process finished with exit code 1
Here is the code of the module:
#! /usr/bin/env python3
# coding: utf-8
import os
import pprint
import logging as lg
import pandas as pd
import matplotlib
matplotlib.use('TkAgg') # you need this if you are on MacOS
import matplotlib.pyplot as plt
import numpy as np
class SetOfParliamentMember:
def __init__(self, name):
self.name = name
def data_from_csv(self, csv_file):
lg.info("Opening data file {}".format(csv_file))
self.dataframe = pd.read_csv(csv_file, sep=";")
def data_from_dataframe(self, dataframe):
self.dataframe = dataframe
def display_chart(self):
data = self.dataframe
female_mps = data[data.sexe == "F"]
male_mps = data[data.sexe == "H"]
counts = [len(female_mps), len(male_mps)]
counts = np.array(counts)
nb_mps = counts.sum()
proportions = counts / nb_mps
labels = ["Female ({})".format(counts[0]), "Male ({})".format(counts[1])]
fig, ax = plt.subplots()
ax.axis("equal")
ax.pie(
proportions,
labels=labels,
autopct="%1.1f%%"
)
plt.title("{} ({} MPs)".format(self.name, nb_mps))
plt.show()
def split_by_political_party(self):
result = {}
data = self.dataframe
# These 2 syntaxes are equivalent : data.parti_ratt_financier and data['parti_ratt_financier']
all_parties = data["parti_ratt_financier"].dropna().unique()
for party in all_parties:
data_subset = data[data.parti_ratt_financier == party]
subset = SetOfParliamentMember('MPs from party "{}"'.format(party))
subset.data_from_dataframe(data_subset)
result[party] = subset
return result
def __str__(self):
names = [] ## todo: remplacer a la fin par une comprehension
for row_index, mp in self.dataframe.iterrows(): ##todo: ici il y a du packing/unpacking
names += [mp.nom]
return str(names) # Python knows how to convert a list into a string
def __repr__(self):
return "SetOfParliamentMember: {} members".format(len(self.dataframe))
def __len__(self):
return self.number_of_mps
def __contains__(self, mp_name):
return mp_name in self.dataframe["nom"].values
def __getitem__(self, index):
try:
result = dict(self.dataframe.iloc[index])
except:
if index < 0:
raise Exception("Please select a positive index")
elif index >= len(self.dataframe):
raise Exception("There are only {} MPs!".format(len(self.dataframe)))
else:
raise Exception("Wrong index")
return result
def __add__(self, other):
if not isinstance(other, SetOfParliamentMember):
raise Exception("Can not add a SetOfParliamentMember with an object of type {}".format(type(other)))
df1, df2 = self.dataframe, other.dataframe ##todo: ici il y a du packing/unpacking
df = df1.append(df2)
df = df.drop_duplicates()
s = SetOfParliamentMember("{} - {}".format(self.name, other.name))
s.data_from_dataframe(df)
return s
def __radd__(self, other): ## todo: l'implementation de cette methode ne suit a mon avis pas les bonnes pratiques
return self
def __lt__(self, other):
return self.number_of_mps < other.number_of_mps
def __gt__(self, other):
return self.number_of_mps > other.number_of_mps
# The following 2 methods are a way to simulate a calculated attribute
# (attribute 'number_of_mps' is calculated from attribute 'seld.dataframe')
# There is a much better way to do it, using decorator '#property'
def __getattr__(self, attr):
if attr == "number_of_mps": ##todo: faire la version avec #property
return len(self.dataframe)
def __setattr__(self, attr, value):
if attr == "number_of_mps":
raise Exception("You can not set the number of MPs!")
self.__dict__[attr] = value ## todo: c'est l'occasion de parler de __dict__ dans le cours ;)
def launch_analysis(data_file,
by_party = False, info = False, displaynames = False,
searchname = None, index = None, groupfirst = None):
sopm = SetOfParliamentMember("All MPs")
sopm.data_from_csv(os.path.join("data",data_file))
sopm.display_chart()
if by_party:
for party, s in sopm.split_by_political_party().items():
s.display_chart()
if info:
print()
print(repr(sopm))
if displaynames:
print()
print(sopm)
if searchname != None:
is_present = searchname in sopm
print()
print("Testing if {} is present: {}".format(searchname, is_present))
if index is not None:
index = int(index)
print()
pprint.pprint(sopm[index]) # prints the dict a nice way
if groupfirst is not None:
groupfirst = int(groupfirst)
parties = sopm.split_by_political_party()
parties = parties.values()
parties_by_size = sorted(parties, reverse = True)
print()
print("Info: the {} biggest groups are :".format(groupfirst))
for p in parties_by_size[0:groupfirst]:
print(p.name)
s = sum(parties_by_size[0:groupfirst])
s.display_chart()
if __name__ == "__main__":
launch_analysis('current_mps.csv')
The script that works and the module folder use the same environment.
Thanks for your help!! (<-- I know that last sentence will be censored, but I'm just polite, you know... that what is called education...)
For those who are having with the Error: cannot import name QUOTE_MINIMAL
Make sure that you don't have a file or folder with the name "csv". This create a name collision problem with the pandas module.
i'm learning with the same project and had the same issue.
Solved it by installing an older pandas version :
pip install pandas==0.25.3
and renaming the file "csv.py".
if not done, 'import pandas as pd' misuses 'csv.py' as module "csv".
Hope it helps
I got the same error, I changed the directory where my code was saved(try Desktop) and it worked, still couln't figure out why I got that error.
Please make sure that you have installed the module you are looking for.

AttributeError: 'compound' object has no attribute '_origin' in vpython.py

What needs to be done to fix this problem?
At https://www.glowscript.org/#/user/murray.garth/folder/Public/program/Eyeballs I found a GlowScript example that i tried to use as a python3 script.
I modified the header to
#https://www.glowscript.org/#/user/murray.garth/folder/Public/program/Eyeballs
#GlowScript 2.1 VPython
from vpython import *
and changed the true/false references to uppercase.
running
python3 eyeballs.py
starts a static image
and then gives the error message:
compound event return
compound event return
compound event return
Traceback (most recent call last):
File "eyeballs.py", line 39, in <module>
world_pos = Head.compound_to_world( vRightEye.pos )
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/vpython/vpython.py", line 1553, in compound_to_world
v = v-self._origin
AttributeError: 'compound' object has no attribute '_origin'
According to https://www.glowscript.org/docs/VPythonDocs/compound.html
the syntax for compound_to_world is:
world_pos = c.compound_to_world(v)
Which seems to be o.k. to me.
The environment is macports python3
python3 --version
Python 3.7.4
I had installed vpython with
pip install vpython
pip --version
pip 18.1 from /opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pip (python 3.7)
Thanks for reporting this bug, which I'll report as an issue in the vpython repository. As you say, a workaround is to specify an origin.
This was a tough one.
There are some 1.2 million questions on python on stackoverflow.
If you search for
[python]"object has no attribute"
you get some 12066 results. So that's probably why this question didn'get much attention.
I tried out the issue with a smaller example according to https://www.glowscript.org/docs/VPythonDocs/compound.html
from vpython import *
handle = cylinder( size=vec(1,.2,.2),color=vec(0.72,0.42,0) )
head = box( size=vec(.2,.6,.2), pos=vec(1.1,0,0),color=color.gray(.6) )
hammer = compound([handle, head])
hammer.axis = vec(1,1,0)
world_pos = hammer.compound_to_world(hammer.axis)
giving the error mentioned in the question:
compound event return
Traceback (most recent call last):
File "hammer.py", line 10, in <module>
print (hammer.origin)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/vpython/vpython.py", line 1536, in origin
return self._origin
AttributeError: 'compound' object has no attribute '_origin'
The relevant source code lines of vpython.py are:
#property
def origin(self):
return self._origin
#origin.setter
def origin(self,value): # compound origin cannot be reset
if not self._constructing:
raise AttributeError('The compound "origin" attribute is read-only; change "pos" instead.')
self._origin = value
def world_to_compound(self, v):
v = v-self._pos
x_axis = self._axis.hat
y_axis = self._up.hat
z_axis = x_axis.cross(y_axis)
ox = self._size0.x/self._size.x # _size0 is the original size
oy = self._size0.y/self._size.y
oz = self._size0.z/self._size.z
return self._origin + vector(v.dot(x_axis)*ox, v.dot(y_axis)*oy, v.dot(z_axis)*oz)
def compound_to_world(self, v):
v = v-self._origin
x_axis = self._axis.hat
y_axis = self._up.hat
z_axis = x_axis.cross(y_axis)
ox = self._size.x/self._size0.x # _size0 is the original size
oy = self._size.y/self._size0.y
oz = self._size.z/self._size0.z
return self._pos + v.x*ox*x_axis + v.y*oy*y_axis + v.z*oz*z_axis
and indeed a few lines further up the constructor does not set any origin.
So adding a default origin:
class compound(standardAttributes):
compound_idx = 0 # same numbering scheme as in GlowScript
def __init__(self, objList, **args):
self._origin = vector(0,0,0)
makes the syntax error go away.
from vpython import *
handle = cylinder( size=vec(1,.2,.2), color=vec(0.72,0.42,0) )
head = box( size=vec(.2,.6,.2), pos=vec(1.1,0,0), color=color.gray(.6) )
hammer = compound([handle, head])
hammer.axis = vec(1,1,0)
print (hammer.origin)
world_pos = hammer.compound_to_world(hammer.axis)
print (world_pos)
then gives the result:
compound event return
<0, 0, 0>
<0.6, 1.41421, 0>
and the eyeballs.py code works as expected:
I do not know there to report this bug but I posted a message to the vpython-users group

ValueError: can't format dates this early

I am trying to get the Next Run Time of a scheduled task using the ITASKDEFINITION but I am having a trouble getting the NextRunTime I am getting the error
Traceback (most recent call last):
File "WSTC.py", line 34, in <module>
print('NextRun : %s\n' % task.NextRunTime)
ValueError: can't format dates this early
Here is the sample code:
import win32com.client
TASK_ENUM_HIDDEN = 0
TASK_STATE = {0: 'Unknown',
1: 'Disabled',
2: 'Queued',
3: 'Ready',
4: 'Running'}
scheduler = win32com.client.Dispatch('Schedule.Service')
scheduler.Connect()
folders = [scheduler.GetFolder('\\')]
n = 0
while folders:
folder = folders.pop(0)
folders += list(folder.GetFolders(0))
tasks = list(folder.GetTasks(TASK_ENUM_HIDDEN))
for task in tasks:
settings = task.Definition.Settings
if TASK_STATE[task.State] == 'Running':
print('Path : %s' % task.Path)
print('State : %s' % TASK_STATE[task.State])
print('NextRun : %s\n' % task.NextRunTime)
n += 1
print ('Listed %d tasks.' % n)
Any assistance or help on this greatly appreciated. Thanks!
After digging deeper and reading about this error. It seems to be that this issue is only in earlier versions of python (I'm using Python 2.7). I tried upgrading python to the latest version and it returns a date lesser than the year 1900 and no longer throws an ValueError exception.
SOURCES:
1
2

Python TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'

Im brand new to python and coding, im trying to get below working.
this is test code and if I can get this working I should be able to build on it.
Like I said im new to this so sorry if its a silly mistake.
# coding=utf-8
import ops # Import the OPS module.
import sys # Import the sys module.
import re
# Subscription processing function
def ops_condition (o):
enter code herestatus, err_str = o.timer.relative("tag",10)
return status
def ops_execute (o):
handle, err_desp = o.cli.open()
print("OPS opens the process of command:",err_desp)
result, n11, n21 = o.cli.execute(handle,"return")
result, n11, n21 = o.cli.execute(handle,"display interface brief | include Ethernet0/0/1")
match = re.search(r"Ethernet0/0/1\s*(\S+)\s*", result)
if not match:
print("Could not determine the state.")
return 0
physical_state = match[1] # Gets the first group from the match.
print (physical_state)
if physical_state == "down":
print("down")
result = o.cli.close(handle)
else :
print("up")
return 0
Error
<setup>('OPS opens the process of command:', 'success')
Oct 17 2018 11:53:39+00:00 setup %%01OPSA/3/OPS_RESULT_EXCEPTION(l)[4]:Script is test.py, current event is tag, instance is 1515334652, exception reason is Trac eback (most recent call last):
File ".lib/frame.py", line 114, in <module>
ret = m.ops_execute(o)
File "flash:$_user/test.py", line 22, in ops_execute
physical_state = match[1] # Gets the first group from the match.
TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'
The __getitem__ method for the regex match objects was only added since Python 3.6. If you're using an earlier version, you can use the group method instead.
Change:
physical_state = match[1]
to:
physical_state = match.group(1)
Please refer to the documentation for details.

Categories