Open2
外国為替MLBot稼働にむけてAIが特徴量を生成するよ#4
記事をよく理解してgoto_detect.pyを作成して。
Claude 3.5 sonnet
from datetime import datetime, timezone, timedelta
import calendar
import jpholiday
import holidays
class GotoDateDetector:
"""
ゴトー日(5の倍数の日)の判定を行うクラス
- 平日(月〜金)であること
- 日本および米国の祝日でないこと
- 翌営業日までの間にゴトー日がある場合は前倒しで当日をゴトー日とする
- 月内の最終営業日は強制的にゴトー日となる
を考慮して判定を行う
"""
def __init__(self):
# 日本のタイムゾーン
self.jst = timezone(timedelta(hours=9))
# ゴトー日のリスト
self.goto_days = {5, 10, 15, 20, 25, 30}
# 米国の祝日カレンダー
self.us_holidays = holidays.US()
def get_date_components(self, timestamp: int) -> tuple:
"""
UNIXタイムスタンプから日付の要素を取得
Args:
timestamp (int): UNIXタイムスタンプ
Returns:
tuple: (datetime object, year, month, day, weekday)
"""
try:
date = datetime.fromtimestamp(timestamp, tz=self.jst)
return (
date,
date.year,
date.month,
date.day,
date.weekday()
)
except (ValueError, TypeError, OSError) as e:
raise ValueError(f"Invalid timestamp: {timestamp}") from e
def is_gotobi(self, day: int) -> bool:
"""
指定された日がゴトー日(5の倍数の日)かどうかを判定
Args:
day (int): 日
Returns:
bool: ゴトー日の場合True
"""
return day in self.goto_days
def is_weekday(self, weekday: int) -> bool:
"""
平日(月〜金)かどうかを判定
Args:
weekday (int): 曜日(0=月曜日, 6=日曜日)
Returns:
bool: 平日の場合True
"""
return 0 <= weekday <= 4
def is_us_holiday(self, date: datetime) -> bool:
"""
米国の祝日かどうかを判定
Args:
date (datetime): 判定対象の日付
Returns:
bool: 米国の祝日の場合True
"""
return date.date() in self.us_holidays
def is_business_day(self, date: datetime) -> bool:
"""
営業日(平日かつ日本・米国の祝日でない日)かどうかを判定
Args:
date (datetime): 判定対象の日付
Returns:
bool: 営業日の場合True
"""
return (self.is_weekday(date.weekday()) and
not jpholiday.is_holiday(date.date()) and
not self.is_us_holiday(date))
def get_next_business_day(self, date: datetime) -> datetime:
"""
次の営業日を取得
Args:
date (datetime): 基準日
Returns:
datetime: 次の営業日
"""
next_date = date + timedelta(days=1)
while not self.is_business_day(next_date):
next_date += timedelta(days=1)
return next_date
def has_gotobi_before_next_business_day(self, date: datetime) -> bool:
"""
次の営業日までの間にゴトー日があるかどうかを判定
Args:
date (datetime): 基準日
Returns:
bool: ゴトー日がある場合True
"""
current = date + timedelta(days=1)
next_business_day = self.get_next_business_day(date)
while current < next_business_day:
if self.is_gotobi(current.day):
return True
current += timedelta(days=1)
return False
def is_last_business_day_of_month(self, date: datetime) -> bool:
"""
月内の最終営業日かどうかを判定
Args:
date (datetime): 判定対象の日付
Returns:
bool: 月内の最終営業日の場合True
"""
# 翌日を取得
next_date = date + timedelta(days=1)
# 翌日が翌月の場合、当日が月末
if next_date.month != date.month:
return self.is_business_day(date)
# 当日から月末まで、当日以外に営業日がない場合は最終営業日
current = next_date
last_day = date.replace(day=calendar.monthrange(date.year, date.month)[1])
while current <= last_day:
if self.is_business_day(current):
return False
current += timedelta(days=1)
return self.is_business_day(date)
def is_valid_gotobi(self, timestamp: int) -> bool:
"""
指定された日時が有効なゴトー日かどうかを判定
- ゴトー日である、または
- 翌営業日までの間にゴトー日があり、当日が営業日である、または
- 月内の最終営業日である
のいずれかの条件を満たす必要がある
Args:
timestamp (int): 判定対象のUNIXタイムスタンプ
Returns:
bool: 有効なゴトー日の場合True
Raises:
ValueError: タイムスタンプが無効な場合
"""
try:
date_obj, _, _, day, _ = self.get_date_components(timestamp)
# 当日が営業日でない場合は False
if not self.is_business_day(date_obj):
return False
# 月内の最終営業日の場合は True
if self.is_last_business_day_of_month(date_obj):
return True
# 当日がゴトー日の場合は True
if self.is_gotobi(day):
return True
# 翌営業日までの間にゴトー日がある場合は True
if self.has_gotobi_before_next_business_day(date_obj):
return True
return False
except ValueError as e:
raise ValueError(f"Error processing timestamp: {e}")
def is_gotobi_weekday_non_holiday(timestamp: int) -> bool:
"""
指定されたUNIXタイムスタンプの日付が有効なゴトー日かどうかを判定する
ユーティリティ関数
Args:
timestamp (int): 判定対象のUNIXタイムスタンプ
Returns:
bool: 有効なゴトー日の場合True
Raises:
ValueError: タイムスタンプが無効な場合
"""
detector = GotoDateDetector()
return detector.is_valid_gotobi(timestamp)