Volatility surface - "AttributeError: 'DataFrame' object has no attribute 'expiration' - python

Working in Colab, starting to build an implied vol surface in Python for 0DTE options trades. imported yfinance, pandas, numby successfully - can't find simple solution to this error?
AttributeError Traceback (most recent call last)
<ipython-input-31-494e77cf0df4> in <module>
----> 1 options = option_chains("ES")
2
3 puts = [options["optionType"] == "put"]
4
5 # print the expirations
1 frames
/usr/local/lib/python3.7/dist-packages/pandas/core/generic.py in __getattr__(self, name)
5485 ):
5486 return self[name]
-> 5487 return object.__getattribute__(self, name)
5488
5489 def __setattr__(self, name: str, value) -> None:
AttributeError: 'DataFrame' object has no attribute 'expiration'
........................
code:
options = option_chains("SPY")
puts = [options["optionType"] == "put"]
# print the expirations
set(puts.expiration)
# select an expiration to plot
puts_at_expiry = puts[puts["expiration"] == "2022-12-2 23:59:59"]
# filter out low vols
filtered_puts_at_expiry = puts_at_expiry[puts_at_expiry.impliedVolatility >= 0.001]
# set the strike as the index so pandas plots nicely filtered_puts_at_expiry[["strike","impliedVolatility"]].set_index("strike").plot(title="Implied Volatility Skew", figsize=(7, 4))
guessing added these 2
from pandas_datareader import data as pdr
!pip install yfinance
in addition to yfinance

Related

How can I select an SAP GuiGridView row via Python scripting

I am trying to use Python for SAP Scripting, specifically to select a row in a GuiGridView object. It works just fine in VB Script, but in Python I get an exception: -2147352562, 'Invalid number of parameters.', which doesn't make sense to me since I'm using the same number of parameters as for VB Script.
I am trying to get away from VB Script since it doesn't have proper error handling.
Here is the documentation (https://help.sap.com/doc/9215986e54174174854b0af6bb14305a/760.01/en-US/sap_gui_scripting_api_761.pdf ), but even with that I haven't been able to resolve this:
Page 128
SelectedRows (Read-write)
Public Property SelectedRows As String
The string is a comma separated list of row index numbers or index ranges, such as “1,2,4-8,10”.Setting this property to an invalid string or a string containing invalid row indices will raise an exception.
The following VB Script code selects the GuiGridRow as expected, but when I attempt to convert that to Python it won't work.
If Not IsObject(application) Then
Set SapGuiAuto = GetObject("SAPGUI")
Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
Set connection = application.Children(0)
End If
If Not IsObject(session) Then
Set session = connection.Children(0)
End If
If IsObject(WScript) Then
WScript.ConnectObject session, "on"
WScript.ConnectObject application, "on"
End If
Set GridView = session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell")
GridView.SelectedRows = 1
Here is my Python 3.9 attempt using Jupyter Notebook and the results:
+*In[1]:*+
import win32com.client
+*In[2]:*+
SapGuiAuto = win32com.client.GetObject('SAPGUI')
application = SapGuiAuto.GetScriptingEngine
connection = application.Children(0)
session = connection.Children(0)
type(session)
+*Out[2]:*+
----win32com.client.CDispatch----
+*In[3]:*+
grid_view = session.findById('wnd[0]/usr/cntlGRID1/shellcont/shell')
print(grid_view)
+*Out[3]:*+
<COMObject <unknown>>
+*In[4]:*+
# to show that grid_view is a valid GuiGridView object
grid_view.RowCount
+*Out[4]:*+
----2----
+*In[5]:*+
# reading the SelectedRows works
grid_view.SelectedRows
+*Out[5]:*+
----'1'----
+*In[6]:*+
# setting SelectedRows as number fails
# note: I had manually unselected the row in SAP before running the rest of the code
grid_view.SelectedRows = 1
+*Out[6]:*+
---------------------------------------------------------------------------
com_error Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/1273355717.py in <module>
----> 1 grid_view.SelectedRows = 1
E:\Anaconda\Lib\site-packages\win32com\client\dynamic.py in __setattr__(self, attr, value)
541 entry = self._olerepr_.propMap[attr]
542 invoke_type = _GetDescInvokeType(entry, pythoncom.INVOKE_PROPERTYPUT)
--> 543 self._oleobj_.Invoke(entry.dispid, 0, invoke_type, 0, value)
544 return
545 # Check the specific "put" map.
com_error: (-2147352562, 'Invalid number of parameters.', None, None)
----
+*In[7]:*+
# setting SelectedRows as string fails
grid_view.SelectedRows = '1'
+*Out[7]:*+
---------------------------------------------------------------------------
com_error Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/1222153478.py in <module>
----> 1 grid_view.SelectedRows = '1'
E:\Anaconda\Lib\site-packages\win32com\client\dynamic.py in __setattr__(self, attr, value)
541 entry = self._olerepr_.propMap[attr]
542 invoke_type = _GetDescInvokeType(entry, pythoncom.INVOKE_PROPERTYPUT)
--> 543 self._oleobj_.Invoke(entry.dispid, 0, invoke_type, 0, value)
544 return
545 # Check the specific "put" map.
com_error: (-2147352562, 'Invalid number of parameters.', None, None)
----
+*In[8]:*+
# setting SelectedRows as string with multiple rows fails
grid_view.SelectedRows = '0,1'
----
+*Out[8]:*+
---------------------------------------------------------------------------
com_error Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/3316141255.py in <module>
----> 1 grid_view.SelectedRows = '0,1'
E:\Anaconda\Lib\site-packages\win32com\client\dynamic.py in __setattr__(self, attr, value)
541 entry = self._olerepr_.propMap[attr]
542 invoke_type = _GetDescInvokeType(entry, pythoncom.INVOKE_PROPERTYPUT)
--> 543 self._oleobj_.Invoke(entry.dispid, 0, invoke_type, 0, value)
544 return
545 # Check the specific "put" map.
com_error: (-2147352562, 'Invalid number of parameters.', None, None)
----
+*In[9]:*+
# setting SelectedRows as string with multiple rows in a method-type notation fails
grid_view.SelectedRows('0,1')
----
+*Out[9]:*+
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/2186236324.py in <module>
----> 1 grid_view.SelectedRows('0,1')
TypeError: 'str' object is not callable
----
Ok, after digging around a lot more, patching to the latest version of win32com worked:
https://github.com/mhammond/pywin32/tree/main/com/win32com
Once I did that all of the following worked to select rows:
grid_view.SelectedRows = 1
grid_view.SelectedRows = '1'
grid_view.SelectedRows = '0,1'
grid_view.SelectedRows = '0-1'
The following did not work (type error), which makes sense since it would imply tuple packing/unpacking:
grid_view.SelectedRows = 0,1
This results in unexpected rows being selected since it is performing subtraction rather than indicating a range of rows:
grid_view.SelectedRows = 0-1

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

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

'GeoDataFrame' object has no attribute 'assign_centroids' in CLIMADA when using admin1

I am using CLIMADA which is a probabilistic natural catastrophe impact model for a project on tropical cyclone impacts in Florida. The following piece of code rises an AttributeError.
import os
import numpy as np
import pandas as pd
import xarray as xr
import netCDF4 as nc
import datetime as dt
# import CLIMADA modules:
from climada.util.constants import SYSTEM_DIR, DATA_DIR # loads default directory paths for data
from climada.engine import Impact
from climada.hazard import TCTracks, Centroids, TropCyclone
from climada.entity import IFTropCyclone, ImpactFuncSet
from climada.entity.exposures.litpop import LitPop
from climada.entity.exposures.litpop import exposure_set_admin1
import climada.util.plot as u_plot
from climada.util.scalebar_plot import scale_bar
# Initiate EXPOSURE:
exp = LitPop()
countries_list = ['USA']
state_list = ['Florida']
exp.set_country(countries_list, admin1_calc = True, res_arcsec=300, reference_year=2014)
exp.set_geometry_points()
exp.set_lat_lon()
exp.check()
exp['if_TC'] = 1
exposure_set_admin1(exp,res_arcsec=300)
exp = exp[exp['admin1'] == 'Florida']
# Initiate TC hazard from tracks and exposure
tc_hazard = TropCyclone()
tc_hazard.set_from_tracks(tracks, centroids=cent)
tc_hazard.check()
# Calculate TC impact from exposure and hazard and creat impact and impact function set (IFS)
# define impact function:
if_tc = IFTropCyclone()
if_tc.haz_type = 'TC'
if_tc.id = 1
if_tc.set_emanuel_usa(v_thresh=25.7, v_half=84.7, scale=1)
IFS = ImpactFuncSet()
IFS.append(if_tc)
# compute impact:
impact = Impact()
impact.calc(exp, IFS, tc_hazard, save_mat=True)
Calling the last line of the code yields:
AttributeError: 'GeoDataFrame' object has no attribute 'assign_centroids'
Can anyone solve the Error?
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-e5655feac3c6> in <module>
1 # compute impact:
2 impact = Impact()
----> 3 impact.calc(exp, IFS, tc_hazard, save_mat=True)
~/Documents/WCR/CLIMADA_develop/climada_python/climada/engine/impact.py in calc(self, exposures, impact_funcs, hazard, save_mat)
153 assign_haz = INDICATOR_CENTR + hazard.tag.haz_type
154 if assign_haz not in exposures:
--> 155 exposures.assign_centroids(hazard)
156 else:
157 LOGGER.info('Exposures matching centroids found in %s', assign_haz)
~/opt/anaconda3/envs/climada_env/lib/python3.7/site-packages/pandas/core/generic.py in __getattr__(self, name)
5065 if self._info_axis._can_hold_identifiers_and_holds_name(name):
5066 return self[name]
-> 5067 return object.__getattribute__(self, name)
5068
5069 def __setattr__(self, name, value):
AttributeError: 'GeoDataFrame' object has no attribute 'assign_centroids'
```
The error occurs when you call the line exp = exp[exp['admin1'] == 'Florida']. This converts your Exposures object to a GeoPandas object. If you would run the exp.check() after this line it would fail.
The solution is to reconvert it back to an Exposures. As all the information is still included in exp this is easy
from climada.entity import Exposures
...
exp = exp[exp['admin1'] == 'Florida']
exp = Exposures(exp)
This is I think an effect of how inherited classes work in Python.

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.

Pulling stock option data with python pandas - broke overnight

Last night I typed up the following
from pandas.io.data import Options
import csv
symList = []
optData = {}
with open('C:/optionstrade/symbols.txt') as symfile:
symreader = csv.reader(symfile, delimiter=',')
for row in symreader:
symList = row
for symbol in symList:
temp = Options(symbol,'yahoo')
try:
optData[symbol] = temp.get_all_data()
except:
pass
It worked alright. I only got data from 200 something of the 400 something symbols I have in the file, but it pulled the options data for those 200 something just fine.
This morning, I go to run the code again (markets have been open for nearly an hour) and I get nothing:
In [6]: len(optData)
Out[6]: 0
So I run a bit of a test:
test = Options('AIG','yahoo')
spam = test.get_all_data()
import pickle
with open('C:/optionstrade/test.txt','w') as testfile:
pickle.dump(test,testfile)
I get this error:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-902aa7c31f7e> in <module>()
1 test = Options('AIG','yahoo')
----> 2 spam = test.get_all_data()
C:\Anaconda\lib\site-packages\pandas\io\data.pyc in get_all_data(self, call, put)
1109
1110 for month in months:
-> 1111 m2 = month.month
1112 y2 = month.year
1113
AttributeError: 'str' object has no attribute 'month'
And this content of the pickled file:
ccopy_reg
_reconstructor
p0
(cpandas.io.data
Options
p1
c__builtin__
object
p2
Ntp3
Rp4
(dp5
S'symbol'
p6
S'AIG'
p7
sb.
Nothing has changed overnight on my end... last thing I did was save and shut down. First thing I did after waking up was run it again.

Categories