Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cron_sim_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.9, "3.10"]
python-version: ["3.10", 3.12]

steps:
- name: Set up Python
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/push_sim_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.9, "3.10"]
python-version: ["3.10", 3.12]

steps:
- name: Set up Python
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ Now, I actually use a `Strategy` class to make decisions for my IRA.

**Skills used:**
<br>
_(bear with me; I'm job-hunting)_

data(Frame) manipulation with `pandas`, fetching data over HTTP with `requests`,
object-oriented programming with abstract base classes, visualization with
Expand Down
18 changes: 18 additions & 0 deletions attr_dict.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/python3

reserved_dict_attrs = set(dir(dict)) | {'__dict__'}

class AttrDict(dict):
'''
Allow keys of a dictionary to also be called like class attributes:
Expand All @@ -25,6 +27,8 @@ def __init__(self, *args, **kwargs):

# Handle setting new keys, turning any nested dicts into AttrDicts as well
def __setitem__(self, key, val):
if isinstance(key, str) and key in reserved_dict_attrs:
raise KeyError(f"Key '{key}' reserved as original dict attribute")
if isinstance(val, dict) and not isinstance(val, AttrDict):
val = AttrDict(val)
super().__setitem__(key, val)
Expand All @@ -36,6 +40,8 @@ def update(self, *args, **kwargs):
# Allow dict keys to be called, set, and deleted like class attributes
def __getattr__(self, name):
try:
# not concerned with reserved attrs since __getattr__ is only called
# when __getattribute__ (which will find them in dict) fails
return self[name]
except KeyError:
raise AttributeError(name)
Expand All @@ -51,3 +57,15 @@ def __delattr__(self, name):
del self[name]
except KeyError:
raise AttributeError(name)

# Allow tab completion
def __dir__(self):
# include normal dict attrs and methods
attrs = set(super().__dir__())

# include AttrDict keys that are valid variable names
# (e.g., no fully numeric or hyphen-containing keys)
attrs.update([key for key in self.keys()
if isinstance(key, str) and key.isidentifier()])

return sorted(attrs)
5 changes: 3 additions & 2 deletions binder/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# required packages for backstroke
matplotlib>=3
numpy<2.3 # up to date as of 1/2025
pandas<2.3 # up to date as of 1/2025
numpy<2.3 # up to date as of 1/2025. v2.3 requires py >3.10. seems OK otherwise
pandas<2.3 # up to date as of 1/2025. v2.3 looks OK if no copy-on-write issues. v3 requires py >3.10 but seems OK otherwise
requests>=2.32.2
python-dotenv
3 changes: 3 additions & 0 deletions binder/start
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
export tiingo="901a2a03f9d57935c22df22ae5a5377cb8de6f22"
exec "$@"
4 changes: 2 additions & 2 deletions buy_and_hold.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
"bnh = BuyAndHoldStrategy(pf,\n",
" start_date=pd.Timestamp(2020, 1, 1),\n",
" end_date=pd.Timestamp(2020, 3, 31),\n",
" cash=1000, reinvest_dividends=True,\n",
" cash=1000, cash_out_dividends=False,\n",
" tot_rb_freq=12, target_rb_day=0)"
]
},
Expand Down Expand Up @@ -395,7 +395,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
"version": "3.9.0"
}
},
"nbformat": 4,
Expand Down
Loading
Loading