fa45d8aa5f
- health_checklist.json: 192.168.1.122→node122
- ocr_client.py: docstring IP→node122
- docs/market-data-requirements.md: IP→node122
- 所有API调用通过ProxyHandler({})绕过系统代理
Privoxy对node122:18003返回500,直连正常
261 lines
7.7 KiB
Python
261 lines
7.7 KiB
Python
#
|
|
# Copyright 2018 Quantopian, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
from datetime import time
|
|
from zoneinfo import ZoneInfo
|
|
|
|
import pandas as pd
|
|
import functools
|
|
|
|
from pandas.tseries.offsets import CustomBusinessDay
|
|
|
|
from exchange_calendars.pandas_extensions.holiday import AbstractHolidayCalendar
|
|
from .tase_holidays import (
|
|
FastDay,
|
|
IndependenceDay,
|
|
MemorialDay,
|
|
NewYear,
|
|
NewYear2,
|
|
NewYearsEve,
|
|
Passover,
|
|
Passover2,
|
|
PassoverInterimDay1,
|
|
PassoverInterimDay1Before2026,
|
|
PassoverInterimDay2,
|
|
PassoverInterimDay2Before2026,
|
|
PassoverInterimDay3,
|
|
PassoverInterimDay3Before2026,
|
|
PassoverInterimDay4,
|
|
PassoverInterimDay4Before2026,
|
|
SukkothInterimDay1,
|
|
SukkothInterimDay1Before2026,
|
|
SukkothInterimDay2,
|
|
SukkothInterimDay2Before2026,
|
|
SukkothInterimDay3,
|
|
SukkothInterimDay3Before2026,
|
|
SukkothInterimDay4,
|
|
SukkothInterimDay4Before2026,
|
|
SukkothInterimDay5,
|
|
SukkothInterimDay5Before2026,
|
|
Passover2Eve,
|
|
PassoverEve,
|
|
Pentecost,
|
|
PentecostEve,
|
|
Purim,
|
|
SimchatTorah,
|
|
SimchatTorahEve,
|
|
Sukkoth,
|
|
SukkothEve,
|
|
YomKippur,
|
|
YomKippurEve,
|
|
YomKippurEveObserved,
|
|
)
|
|
from .exchange_calendar import HolidayCalendar, ExchangeCalendar
|
|
from .pandas_extensions.offsets import MultipleWeekmaskCustomBusinessDay
|
|
|
|
# All holidays are defined as ad-hoc holidays for each year since there is
|
|
# currently no support for Hebrew calendar holiday rules in pandas.
|
|
|
|
HOLIDAY_EARLY_CLOSE = time(14, 15)
|
|
SUNDAY_CLOSE = time(15, 40)
|
|
FRIDAY_CLOSE = time(13, 50)
|
|
|
|
|
|
class SundayUntil2026(HolidayCalendar):
|
|
def __init__(self):
|
|
super().__init__(rules=[])
|
|
|
|
def holidays(self, start=None, end=None, return_name=False): # noqa: ARG002
|
|
limit = pd.Timestamp("2026-01-05")
|
|
if start is None:
|
|
start = pd.Timestamp(AbstractHolidayCalendar.start_date)
|
|
if end is None:
|
|
end = pd.Timestamp(AbstractHolidayCalendar.end_date)
|
|
effective_end = min(end, limit)
|
|
if start > effective_end:
|
|
return pd.DatetimeIndex([])
|
|
return pd.date_range(start, effective_end, freq="W-SUN")
|
|
|
|
|
|
class FridayFrom2026(HolidayCalendar):
|
|
def __init__(self):
|
|
super().__init__(rules=[])
|
|
|
|
def holidays(self, start=None, end=None, return_name=False): # noqa: ARG002
|
|
limit = pd.Timestamp("2026-01-05")
|
|
if start is None:
|
|
start = pd.Timestamp(AbstractHolidayCalendar.start_date)
|
|
if end is None:
|
|
end = pd.Timestamp(AbstractHolidayCalendar.end_date)
|
|
effective_start = max(start, limit)
|
|
if effective_start > end:
|
|
return pd.DatetimeIndex([])
|
|
return pd.date_range(effective_start, end, freq="W-FRI")
|
|
|
|
|
|
class XTAEExchangeCalendar(ExchangeCalendar):
|
|
"""
|
|
Exchange calendar for TASE Stock Exchange.
|
|
|
|
Open/close times are continuous trading times valid Mon-Thu for Shares
|
|
Group A. Trading schedule differs on Sundays.
|
|
|
|
Open Time: 9:59 AM, Asia/Tel_Aviv (randomly between 9:59 and 10:00).
|
|
Close Time: 5:15 PM, Asia/Tel_Aviv (randomly between 5:14 and 5:15).
|
|
Friday close time: 1:50pm, Asia/Tel_Aviv
|
|
|
|
Regularly-Observed Holidays (not necessarily in order):
|
|
- Purim
|
|
- Passover Eve
|
|
- Passover
|
|
- Passover II Eve
|
|
- Passover II
|
|
- Memorial Day
|
|
- Independence Day
|
|
- Pentecost Eve
|
|
- Pentecost
|
|
- Tisha B'Av
|
|
- New Year's Eve
|
|
- New Year
|
|
- New Year II
|
|
- Yom Kippur Eve
|
|
- Yom Kippur
|
|
- Sukkoth Eve
|
|
- Sukkoth
|
|
- Simchat Torah Eve
|
|
- Simchat Torah
|
|
|
|
Note these dates are only checked against 2019-2026.
|
|
|
|
https://www.tase.co.il/en/content/knowledge_center/trading_vacation_schedule
|
|
|
|
Daylight Saving Time in Israel comes into effect on the Friday before the
|
|
last Sunday in March, and lasts until the last Sunday in October. During the
|
|
Daylight Saving time period the clock will be UTC+3, and UTC+2 for the rest
|
|
of the year.
|
|
|
|
Transition to Monday-Friday Trading
|
|
https://www.tase.co.il/en/content/about/tradingdays_change
|
|
"""
|
|
|
|
name = "XTAE"
|
|
|
|
tz = ZoneInfo("Asia/Tel_Aviv")
|
|
|
|
open_times = ((None, time(9, 59)),)
|
|
|
|
close_times = ((None, time(17, 15)),)
|
|
|
|
@property
|
|
def regular_holidays(self):
|
|
return HolidayCalendar(
|
|
[
|
|
Purim,
|
|
PassoverEve,
|
|
Passover,
|
|
Passover2Eve,
|
|
Passover2,
|
|
MemorialDay,
|
|
IndependenceDay,
|
|
PentecostEve,
|
|
Pentecost,
|
|
FastDay,
|
|
NewYearsEve,
|
|
NewYear,
|
|
NewYear2,
|
|
YomKippurEve,
|
|
YomKippurEveObserved,
|
|
YomKippur,
|
|
SukkothEve,
|
|
Sukkoth,
|
|
SimchatTorahEve,
|
|
SimchatTorah,
|
|
]
|
|
)
|
|
|
|
@property
|
|
def adhoc_holidays(self):
|
|
return [
|
|
# Election days:
|
|
# - 2019
|
|
pd.Timestamp("2019-04-09"),
|
|
pd.Timestamp("2019-09-17"),
|
|
# - 2020
|
|
pd.Timestamp("2020-03-02"),
|
|
# - 2021
|
|
pd.Timestamp("2021-03-23"),
|
|
# - 2022
|
|
pd.Timestamp("2022-11-01"),
|
|
]
|
|
|
|
@property
|
|
def special_closes(self):
|
|
return [
|
|
(
|
|
HOLIDAY_EARLY_CLOSE,
|
|
HolidayCalendar(
|
|
[
|
|
PassoverInterimDay1,
|
|
PassoverInterimDay2,
|
|
PassoverInterimDay3,
|
|
PassoverInterimDay4,
|
|
PassoverInterimDay1Before2026,
|
|
PassoverInterimDay2Before2026,
|
|
PassoverInterimDay3Before2026,
|
|
PassoverInterimDay4Before2026,
|
|
SukkothInterimDay1,
|
|
SukkothInterimDay2,
|
|
SukkothInterimDay3,
|
|
SukkothInterimDay4,
|
|
SukkothInterimDay5,
|
|
SukkothInterimDay1Before2026,
|
|
SukkothInterimDay2Before2026,
|
|
SukkothInterimDay3Before2026,
|
|
SukkothInterimDay4Before2026,
|
|
SukkothInterimDay5Before2026,
|
|
]
|
|
),
|
|
),
|
|
(SUNDAY_CLOSE, SundayUntil2026()),
|
|
(FRIDAY_CLOSE, FridayFrom2026()),
|
|
]
|
|
|
|
@property
|
|
def special_weekmasks(self):
|
|
"""
|
|
Returns
|
|
-------
|
|
list: List of (date, date, str) tuples that represent special
|
|
weekmasks that applies between dates.
|
|
"""
|
|
return [
|
|
(None, pd.Timestamp("2026-01-04"), "1111001"),
|
|
]
|
|
|
|
@functools.cached_property
|
|
def day(self):
|
|
if self.special_weekmasks:
|
|
return MultipleWeekmaskCustomBusinessDay(
|
|
holidays=self.adhoc_holidays,
|
|
calendar=self.regular_holidays,
|
|
weekmask=self.weekmask,
|
|
weekmasks=self.special_weekmasks,
|
|
)
|
|
return CustomBusinessDay(
|
|
holidays=self.adhoc_holidays,
|
|
calendar=self.regular_holidays,
|
|
weekmask=self.weekmask,
|
|
)
|