Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError: 'datetime.timezone' object has no attribute 'key' in calendar_helpers.py #408

Closed
gmaubach opened this issue Jul 27, 2024 · 3 comments

Comments

@gmaubach
Copy link

Description

I encountered an AttributeError while using the exchange_calendars library. The error occurs in the parse_date function in calendar_helpers.py.

Expected Behaviour

The time-ware date should be parsed without any errors.

Actual Behaviour

An AttributeError is raised indicating that 'datetime.timezone' object has no attribute 'key'.

Environment

OS: Debian GNU Linux 12 Bookworm
Build: Linux version 6.1.0-23-amd64 ([email protected]) (gcc-12 (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40) #1 SMP PREEMPT_DYNAMIC Debian 6.1.99-1 (2024-07-15)
Package Management: conda (Minoconda3 Python 3.10)
Environment: see attached environment.yml file named "environment_yml.txt"
Python: 3.10.13
Module Version: exchange-calendars=4.5.5=pyhd8ed1ab_0

Steps to Reproduce

  • I highlighted the issue with "!!!!--- Issue Start ---!!!!" and "!!!--- Issue End ---!!!".

Version with timezone-aware dates

Source

#!/usr/bin/env python
# coding: utf-8

# -- -----------------------------------

import zipline
from zipline.api import order_target_percent, symbol, schedule_function, date_rules, time_rules
from datetime import datetime
import pytz
from matplotlib import pyplot as plt
import pandas as pd

# -- -----------------------------------

def initialize(context):
    # Securities and target weights
    context.securities = {
        'SPY': 0.25, 
        'TLT': 0.3, 
        'IEF': 0.3, 
        'GLD': 0.075, 
        'DBC': 0.075
    }
    
    # Schedule rebalance for once a month
    schedule_function(rebalance, date_rules.month_start(), time_rules.market_open())

# -- -----------------------------------

def rebalance(context, data):
    # Loop through the securities
    for sec, weight in context.securities.items():
        sym = symbol(sec)
        # Check if we can trade
        if data.can_trade(sym):
            # Reset the weight
            order_target_percent(sym, weight) 

# -- -----------------------------------

# Set start and end
!!!!--- Issue Start ---!!!
start = datetime(1997, 1, 1, 8, 15, 12, 0, pytz.UTC)
end = datetime(2018, 12, 31, 8, 15, 12, 0, pytz.UTC)

# start_naive = start.replace(tzinfo=None)
# end_naive = end.replace(tzinfo=None)
!!!--- Issue End ---!!!

# Fire off backtest
result = zipline.run_algorithm(
    start=start, # Set start
    end=end,  # Set end
    initialize=initialize, # Define startup function
    capital_base=100000, # Set initial capital
    data_frequency = 'daily',  # Set data frequency
    bundle='ac_equities_db' ) # Select bundle

print("Ready to analyze result.")

Traceback

File ~/miniconda3/envs/lab4/lib/python3.10/site-packages/exchange_calendars/calendar_helpers.py:379, in parse_date(date, param_name, calendar, raise_oob)
    375 ts = parse_timestamp(date, param_name, raise_oob=False, side="left", utc=False)
    377 if ts.tz is not None:
    378     raise ValueError(
--> 379         f"Parameter `{param_name}` received with timezone defined as '{ts.tz.key}'"
    380         f" although a Date must be timezone naive."
    381     )
    383 if not ts == ts.normalize():
    384     raise ValueError(
    385         f"Parameter `{param_name}` parsed as '{ts}' although a Date must have"
    386         f" a time component of 00:00."
    387     )

AttributeError: 'UTC' object has no attribute 'key'

Version with time-unaware dates

Source

#!/usr/bin/env python
# coding: utf-8

# -- -----------------------------------

import zipline
from zipline.api import order_target_percent, symbol, schedule_function, date_rules, time_rules
from datetime import datetime
import pytz
from matplotlib import pyplot as plt
import pandas as pd

# -- -----------------------------------

def initialize(context):
    # Securities and target weights
    context.securities = {
        'SPY': 0.25, 
        'TLT': 0.3, 
        'IEF': 0.3, 
        'GLD': 0.075, 
        'DBC': 0.075
    }
    
    # Schedule rebalance for once a month
    schedule_function(rebalance, date_rules.month_start(), time_rules.market_open())

# -- -----------------------------------

def rebalance(context, data):
    # Loop through the securities
    for sec, weight in context.securities.items():
        sym = symbol(sec)
        # Check if we can trade
        if data.can_trade(sym):
            # Reset the weight
            order_target_percent(sym, weight) 

# -- -----------------------------------

# Set start and end
!!!!--- Issue Start ---!!!
start = datetime(1997, 1, 1, 8, 15, 12, 0, pytz.UTC)
end = datetime(2018, 12, 31, 8, 15, 12, 0, pytz.UTC)

start_naive = start.replace(tzinfo=None)
end_naive = end.replace(tzinfo=None)
!!!!--- Issue End ---!!!

# Fire off backtest
result = zipline.run_algorithm(
    start=start_naive, # Set start
    end=end_naive,  # Set end
    initialize=initialize, # Define startup function
    capital_base=100000, # Set initial capital
    data_frequency = 'daily',  # Set data frequency
    bundle='ac_equities_db' ) # Select bundle

print("Ready to analyze result.")

Traceback

File ~/miniconda3/envs/lab4/lib/python3.10/site-packages/exchange_calendars/calendar_helpers.py:384, in parse_date(date, param_name, calendar, raise_oob)
    378     raise ValueError(
    379         f"Parameter `{param_name}` received with timezone defined as '{ts.tz.key}'"
    380         f" although a Date must be timezone naive."
    381     )
    383 if not ts == ts.normalize():
--> 384     raise ValueError(
    385         f"Parameter `{param_name}` parsed as '{ts}' although a Date must have"
    386         f" a time component of 00:00."
    387     )
    389 if raise_oob:
    390     if calendar is None:

ValueError: Parameter `start` parsed as '1997-01-01 08:15:00' although a Date must have a time component of 00:00.

Attachments

environment_yml.txt

@maread99
Copy link
Collaborator

Hi @gmaubach, sorry for the late reply.

This doesn't appear to be an issue with exchange_calendars but rather with the values that zipline is passing through to it (zipline hasn't been maintained for years).

Looking at the traceback, I'm wondering if it might not be as simple as needing to define your 'start' and 'end' values without a time component. I'd try that, again with timezone-naive values, for example:

import datetime
start = datetime.datetime(2018, 12, 31)

Let us know if that doesn't fix it.

@jimwhite
Copy link

jimwhite commented Oct 1, 2024

Hi @gmaubach, sorry for the late reply.

This doesn't appear to be an issue with exchange_calendars but rather with the values that zipline is passing through to it (zipline hasn't been maintained for years).

Looking at the traceback, I'm wondering if it might not be as simple as needing to define your 'start' and 'end' values without a time component. I'd try that, again with timezone-naive values, for example:

import datetime
start = datetime.datetime(2018, 12, 31)

Let us know if that doesn't fix it.

I don't think that is the correct way to deal with this. As I say here stefan-jansen/zipline-reloaded#265 I think this is a bug in Zipline. Would like to get your feedback because I'd like to fix this.

@maread99
Copy link
Collaborator

Hi @jimwhite. Sorry but I can't offer any worthwhile insight on the zipline issue - I'm not familiar with the package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants