feat(indicators): add indicator service and related dataclasses
This commit is contained in:
parent
4fb70813e6
commit
600d6b76f6
@ -33,7 +33,8 @@ class TradingDataCRUD:
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def get_session(self):
|
def get_session(self):
|
||||||
"""Context manager for database sessions with automatic cleanup."""
|
"""Context manager for database sessions with automatic cleanup."""
|
||||||
session = Session(self.engine)
|
session = Session(self.engine, expire_on_commit=False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield session
|
yield session
|
||||||
session.commit()
|
session.commit()
|
||||||
|
360
paperone/indicators.py
Normal file
360
paperone/indicators.py
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
import talib
|
||||||
|
import numpy as np
|
||||||
|
from typing import List
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from .models import (
|
||||||
|
TickerOHLCV,
|
||||||
|
IndicatorsData,
|
||||||
|
MarketRegimeIndicators,
|
||||||
|
MomentumIndicators,
|
||||||
|
VolatilityIndicators,
|
||||||
|
VolumeIndicators,
|
||||||
|
SupportResistanceIndicators,
|
||||||
|
TrendIndicators,
|
||||||
|
OHLCVArrays,
|
||||||
|
)
|
||||||
|
from .database import TradingDataCRUD
|
||||||
|
|
||||||
|
|
||||||
|
class IndicatorService:
|
||||||
|
"""
|
||||||
|
Middleware service for calculating technical indicators from stored OHLCV data.
|
||||||
|
|
||||||
|
This service:
|
||||||
|
1. Fetches historical OHLCV data from the database
|
||||||
|
2. Calculates all 29 technical indicators using TA-Lib
|
||||||
|
3. Returns strongly-typed IndicatorsData ready to be saved
|
||||||
|
|
||||||
|
All calculations are done locally without external API calls.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, crud: TradingDataCRUD):
|
||||||
|
"""
|
||||||
|
Initialize the indicator service with database access.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
crud: TradingDataCRUD instance for database operations
|
||||||
|
"""
|
||||||
|
self._crud: TradingDataCRUD = crud
|
||||||
|
|
||||||
|
def calculate_indicators_for_date(
|
||||||
|
self, ticker: str, target_date: datetime, lookback_days: int = 50
|
||||||
|
) -> IndicatorsData | None:
|
||||||
|
"""
|
||||||
|
Calculate all indicators for a ticker on a specific date using stored OHLCV data.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ticker: Stock ticker symbol
|
||||||
|
target_date: Date to calculate indicators for
|
||||||
|
lookback_days: Number of historical days needed for calculations (default: 50)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
IndicatorsData instance ready to save to database, or None if insufficient data
|
||||||
|
"""
|
||||||
|
# Fetch historical OHLCV data from database
|
||||||
|
start_date: datetime = target_date - timedelta(
|
||||||
|
days=lookback_days * 2
|
||||||
|
) # Buffer for weekends
|
||||||
|
ohlcv_records: List[TickerOHLCV] = self._crud.get_ohlcv_range(
|
||||||
|
ticker=ticker, start_date=start_date, end_date=target_date
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verify we have enough data
|
||||||
|
if len(ohlcv_records) < 30:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Convert to numpy arrays for TA-Lib
|
||||||
|
arrays: OHLCVArrays = self._convert_to_arrays(ohlcv_records)
|
||||||
|
|
||||||
|
# Calculate all indicator categories
|
||||||
|
momentum: MomentumIndicators = self._calculate_momentum(arrays)
|
||||||
|
volatility: VolatilityIndicators = self._calculate_volatility(arrays)
|
||||||
|
trend: TrendIndicators = self._calculate_trend(arrays)
|
||||||
|
volume: VolumeIndicators = self._calculate_volume(arrays)
|
||||||
|
support_resistance: SupportResistanceIndicators = (
|
||||||
|
self._calculate_support_resistance(arrays)
|
||||||
|
)
|
||||||
|
market_regime: MarketRegimeIndicators = self._calculate_market_regime(arrays)
|
||||||
|
|
||||||
|
# Build and return strongly-typed IndicatorsData
|
||||||
|
return IndicatorsData(
|
||||||
|
ticker=ticker,
|
||||||
|
date=target_date,
|
||||||
|
|
||||||
|
# Momentum (7 indicators)
|
||||||
|
|
||||||
|
rsi_14=momentum.rsi_14,
|
||||||
|
rsi_20=momentum.rsi_20,
|
||||||
|
macd_line=momentum.macd_line,
|
||||||
|
macd_signal=momentum.macd_signal,
|
||||||
|
macd_histogram=momentum.macd_histogram,
|
||||||
|
stoch_k=momentum.stoch_k,
|
||||||
|
stoch_d=momentum.stoch_d,
|
||||||
|
|
||||||
|
# Volatility (6 indicators)
|
||||||
|
|
||||||
|
bb_upper=volatility.bb_upper,
|
||||||
|
bb_middle=volatility.bb_middle,
|
||||||
|
bb_lower=volatility.bb_lower,
|
||||||
|
bb_width=volatility.bb_width,
|
||||||
|
bb_percent=volatility.bb_percent,
|
||||||
|
atr_14=volatility.atr_14,
|
||||||
|
|
||||||
|
# Trend (4 indicators)
|
||||||
|
|
||||||
|
adx_14=trend.adx_14,
|
||||||
|
di_plus=trend.di_plus,
|
||||||
|
di_minus=trend.di_minus,
|
||||||
|
sar=trend.sar,
|
||||||
|
|
||||||
|
# Volume (3 indicators)
|
||||||
|
|
||||||
|
obv=volume.obv,
|
||||||
|
obv_sma_20=volume.obv_sma_20,
|
||||||
|
volume_roc_5=volume.volume_roc_5,
|
||||||
|
|
||||||
|
# Support/Resistance (6 indicators)
|
||||||
|
|
||||||
|
fib_236=support_resistance.fib_236,
|
||||||
|
fib_382=support_resistance.fib_382,
|
||||||
|
fib_618=support_resistance.fib_618,
|
||||||
|
pivot_point=support_resistance.pivot_point,
|
||||||
|
resistance_1=support_resistance.resistance_1,
|
||||||
|
support_1=support_resistance.support_1,
|
||||||
|
|
||||||
|
# Market Regime (2 indicators)
|
||||||
|
|
||||||
|
cci_20=market_regime.cci_20,
|
||||||
|
williams_r_14=market_regime.williams_r_14,
|
||||||
|
)
|
||||||
|
|
||||||
|
def calculate_and_save_indicators(
|
||||||
|
self, ticker: str, target_date: datetime
|
||||||
|
) -> IndicatorsData | None:
|
||||||
|
"""
|
||||||
|
Calculate indicators and immediately save them to the database.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ticker: Stock ticker symbol
|
||||||
|
target_date: Date to calculate indicators for
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Saved IndicatorsData instance or None if calculation failed
|
||||||
|
"""
|
||||||
|
indicators: IndicatorsData | None = self.calculate_indicators_for_date(
|
||||||
|
ticker=ticker, target_date=target_date
|
||||||
|
)
|
||||||
|
|
||||||
|
if indicators is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Upsert (insert or update if exists)
|
||||||
|
return self._crud.upsert_indicators(indicators)
|
||||||
|
|
||||||
|
def bulk_calculate_indicators(
|
||||||
|
self, ticker: str, dates: List[datetime]
|
||||||
|
) -> List[IndicatorsData]:
|
||||||
|
"""
|
||||||
|
Calculate indicators for multiple dates efficiently.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ticker: Stock ticker symbol
|
||||||
|
dates: List of dates to calculate indicators for
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of IndicatorsData instances (may be less than input if some failed)
|
||||||
|
"""
|
||||||
|
results: List[IndicatorsData] = []
|
||||||
|
|
||||||
|
for date in dates:
|
||||||
|
indicators: IndicatorsData | None = self.calculate_indicators_for_date(
|
||||||
|
ticker=ticker, target_date=date
|
||||||
|
)
|
||||||
|
if indicators is not None:
|
||||||
|
results.append(indicators)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def bulk_calculate_and_save_indicators(
|
||||||
|
self, ticker: str, dates: List[datetime]
|
||||||
|
) -> int:
|
||||||
|
"""
|
||||||
|
Calculate and save indicators for multiple dates efficiently.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ticker: Stock ticker symbol
|
||||||
|
dates: List of dates to calculate indicators for
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Number of indicator records successfully saved
|
||||||
|
"""
|
||||||
|
indicators_list: List[IndicatorsData] = self.bulk_calculate_indicators(
|
||||||
|
ticker=ticker, dates=dates
|
||||||
|
)
|
||||||
|
|
||||||
|
if not indicators_list:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return self._crud.create_indicators_bulk(indicators_list)
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# PRIVATE: Data Conversion
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _convert_to_arrays(ohlcv_records: List[TickerOHLCV]) -> "OHLCVArrays":
|
||||||
|
"""Convert list of TickerOHLCV records to numpy arrays for TA-Lib."""
|
||||||
|
return OHLCVArrays(
|
||||||
|
open=np.array([r.open for r in ohlcv_records], dtype=np.float64),
|
||||||
|
high=np.array([r.high for r in ohlcv_records], dtype=np.float64),
|
||||||
|
low=np.array([r.low for r in ohlcv_records], dtype=np.float64),
|
||||||
|
close=np.array([r.close for r in ohlcv_records], dtype=np.float64),
|
||||||
|
volume=np.array([r.volume for r in ohlcv_records], dtype=np.float64),
|
||||||
|
)
|
||||||
|
|
||||||
|
# ========================================================================
|
||||||
|
# PRIVATE: Indicator Calculations
|
||||||
|
# ========================================================================
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _calculate_momentum(arrays: "OHLCVArrays") -> "MomentumIndicators":
|
||||||
|
"""Calculate momentum indicators (RSI, MACD, Stochastic)."""
|
||||||
|
rsi_14: float = float(talib.RSI(arrays.close, timeperiod=14)[-1])
|
||||||
|
rsi_20: float = float(talib.RSI(arrays.close, timeperiod=20)[-1])
|
||||||
|
|
||||||
|
macd_line_arr, macd_signal_arr, macd_hist_arr = talib.MACD(
|
||||||
|
arrays.close, fastperiod=12, slowperiod=26, signalperiod=9
|
||||||
|
)
|
||||||
|
|
||||||
|
stoch_k_arr, stoch_d_arr = talib.STOCH(
|
||||||
|
arrays.high,
|
||||||
|
arrays.low,
|
||||||
|
arrays.close,
|
||||||
|
fastk_period=14,
|
||||||
|
slowk_period=3,
|
||||||
|
slowd_period=3,
|
||||||
|
)
|
||||||
|
|
||||||
|
return MomentumIndicators(
|
||||||
|
rsi_14=round(rsi_14, 2),
|
||||||
|
rsi_20=round(rsi_20, 2),
|
||||||
|
macd_line=round(float(macd_line_arr[-1]), 4),
|
||||||
|
macd_signal=round(float(macd_signal_arr[-1]), 4),
|
||||||
|
macd_histogram=round(float(macd_hist_arr[-1]), 4),
|
||||||
|
stoch_k=round(float(stoch_k_arr[-1]), 2),
|
||||||
|
stoch_d=round(float(stoch_d_arr[-1]), 2),
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _calculate_volatility(arrays: "OHLCVArrays") -> "VolatilityIndicators":
|
||||||
|
"""Calculate volatility indicators (Bollinger Bands, ATR)."""
|
||||||
|
bb_upper_arr, bb_middle_arr, bb_lower_arr = talib.BBANDS(
|
||||||
|
arrays.close, timeperiod=20, nbdevup=2, nbdevdn=2
|
||||||
|
)
|
||||||
|
|
||||||
|
bb_upper: float = float(bb_upper_arr[-1])
|
||||||
|
bb_middle: float = float(bb_middle_arr[-1])
|
||||||
|
bb_lower: float = float(bb_lower_arr[-1])
|
||||||
|
bb_width: float = bb_upper - bb_lower
|
||||||
|
bb_percent: float = (
|
||||||
|
(arrays.close[-1] - bb_lower) / (bb_upper - bb_lower)
|
||||||
|
if bb_width > 0
|
||||||
|
else 0.5
|
||||||
|
)
|
||||||
|
|
||||||
|
atr_14: float = float(
|
||||||
|
talib.ATR(arrays.high, arrays.low, arrays.close, timeperiod=14)[-1]
|
||||||
|
)
|
||||||
|
|
||||||
|
return VolatilityIndicators(
|
||||||
|
bb_upper=round(bb_upper, 2),
|
||||||
|
bb_middle=round(bb_middle, 2),
|
||||||
|
bb_lower=round(bb_lower, 2),
|
||||||
|
bb_width=round(bb_width, 2),
|
||||||
|
bb_percent=round(bb_percent, 4),
|
||||||
|
atr_14=round(atr_14, 2),
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _calculate_trend(arrays: "OHLCVArrays") -> "TrendIndicators":
|
||||||
|
"""Calculate trend indicators (ADX, DI+, DI-, SAR)."""
|
||||||
|
adx_14: float = float(
|
||||||
|
talib.ADX(arrays.high, arrays.low, arrays.close, timeperiod=14)[-1]
|
||||||
|
)
|
||||||
|
di_plus: float = float(
|
||||||
|
talib.PLUS_DI(arrays.high, arrays.low, arrays.close, timeperiod=14)[-1]
|
||||||
|
)
|
||||||
|
di_minus: float = float(
|
||||||
|
talib.MINUS_DI(arrays.high, arrays.low, arrays.close, timeperiod=14)[-1]
|
||||||
|
)
|
||||||
|
sar: float = float(
|
||||||
|
talib.SAR(arrays.high, arrays.low, acceleration=0.02, maximum=0.2)[-1]
|
||||||
|
)
|
||||||
|
|
||||||
|
return TrendIndicators(
|
||||||
|
adx_14=round(adx_14, 2),
|
||||||
|
di_plus=round(di_plus, 2),
|
||||||
|
di_minus=round(di_minus, 2),
|
||||||
|
sar=round(sar, 2),
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _calculate_volume(arrays: "OHLCVArrays") -> "VolumeIndicators":
|
||||||
|
"""Calculate volume indicators (OBV, Volume ROC)."""
|
||||||
|
obv_arr: np.ndarray = talib.OBV(arrays.close, arrays.volume)
|
||||||
|
obv: float = float(obv_arr[-1])
|
||||||
|
obv_sma_20: float = float(talib.SMA(obv_arr, timeperiod=20)[-1])
|
||||||
|
volume_roc_5: float = float(talib.ROC(arrays.volume, timeperiod=5)[-1])
|
||||||
|
|
||||||
|
return VolumeIndicators(
|
||||||
|
obv=round(obv, 0),
|
||||||
|
obv_sma_20=round(obv_sma_20, 0),
|
||||||
|
volume_roc_5=round(volume_roc_5, 2),
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _calculate_support_resistance(
|
||||||
|
arrays: "OHLCVArrays",
|
||||||
|
) -> "SupportResistanceIndicators":
|
||||||
|
"""Calculate support/resistance levels (Fibonacci, Pivot Points)."""
|
||||||
|
# Fibonacci retracements (last 30 days)
|
||||||
|
lookback: int = min(30, len(arrays.high))
|
||||||
|
max_price: float = float(np.max(arrays.high[-lookback:]))
|
||||||
|
min_price: float = float(np.min(arrays.low[-lookback:]))
|
||||||
|
diff: float = max_price - min_price
|
||||||
|
|
||||||
|
fib_236: float = max_price - (diff * 0.236)
|
||||||
|
fib_382: float = max_price - (diff * 0.382)
|
||||||
|
fib_618: float = max_price - (diff * 0.618)
|
||||||
|
|
||||||
|
# Pivot points (previous day's data)
|
||||||
|
high_prev: float = float(arrays.high[-1])
|
||||||
|
low_prev: float = float(arrays.low[-1])
|
||||||
|
close_prev: float = float(arrays.close[-1])
|
||||||
|
|
||||||
|
pivot_point: float = (high_prev + low_prev + close_prev) / 3
|
||||||
|
resistance_1: float = (2 * pivot_point) - low_prev
|
||||||
|
support_1: float = (2 * pivot_point) - high_prev
|
||||||
|
|
||||||
|
return SupportResistanceIndicators(
|
||||||
|
fib_236=round(fib_236, 2),
|
||||||
|
fib_382=round(fib_382, 2),
|
||||||
|
fib_618=round(fib_618, 2),
|
||||||
|
pivot_point=round(pivot_point, 2),
|
||||||
|
resistance_1=round(resistance_1, 2),
|
||||||
|
support_1=round(support_1, 2),
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _calculate_market_regime(arrays: "OHLCVArrays") -> "MarketRegimeIndicators":
|
||||||
|
"""Calculate market regime indicators (CCI, Williams %R)."""
|
||||||
|
cci_20: float = float(
|
||||||
|
talib.CCI(arrays.high, arrays.low, arrays.close, timeperiod=20)[-1]
|
||||||
|
)
|
||||||
|
williams_r_14: float = float(
|
||||||
|
talib.WILLR(arrays.high, arrays.low, arrays.close, timeperiod=14)[-1]
|
||||||
|
)
|
||||||
|
|
||||||
|
return MarketRegimeIndicators(
|
||||||
|
cci_20=round(cci_20, 2), williams_r_14=round(williams_r_14, 2)
|
||||||
|
)
|
@ -1,6 +1,8 @@
|
|||||||
from sqlmodel import SQLModel, Field, Relationship, ForeignKeyConstraint
|
from sqlmodel import SQLModel, Field, Relationship, ForeignKeyConstraint
|
||||||
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class TickerOHLCV(SQLModel, table=True):
|
class TickerOHLCV(SQLModel, table=True):
|
||||||
@ -84,3 +86,78 @@ class IndicatorsData(SQLModel, table=True):
|
|||||||
|
|
||||||
# One-to-one relationship back to TickerOHLCV
|
# One-to-one relationship back to TickerOHLCV
|
||||||
ohlcv: TickerOHLCV = Relationship(back_populates="indicators")
|
ohlcv: TickerOHLCV = Relationship(back_populates="indicators")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class OHLCVArrays:
|
||||||
|
"""Numpy arrays of OHLCV data for TA-Lib calculations."""
|
||||||
|
|
||||||
|
open: np.ndarray
|
||||||
|
high: np.ndarray
|
||||||
|
low: np.ndarray
|
||||||
|
close: np.ndarray
|
||||||
|
volume: np.ndarray
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MomentumIndicators:
|
||||||
|
"""Momentum indicator values (RSI, MACD, Stochastic)."""
|
||||||
|
|
||||||
|
rsi_14: float
|
||||||
|
rsi_20: float
|
||||||
|
macd_line: float
|
||||||
|
macd_signal: float
|
||||||
|
macd_histogram: float
|
||||||
|
stoch_k: float
|
||||||
|
stoch_d: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class VolatilityIndicators:
|
||||||
|
"""Volatility indicator values (Bollinger Bands, ATR)."""
|
||||||
|
|
||||||
|
bb_upper: float
|
||||||
|
bb_middle: float
|
||||||
|
bb_lower: float
|
||||||
|
bb_width: float
|
||||||
|
bb_percent: float
|
||||||
|
atr_14: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class TrendIndicators:
|
||||||
|
"""Trend indicator values (ADX, DI+, DI-, SAR)."""
|
||||||
|
|
||||||
|
adx_14: float
|
||||||
|
di_plus: float
|
||||||
|
di_minus: float
|
||||||
|
sar: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class VolumeIndicators:
|
||||||
|
"""Volume indicator values (OBV, Volume ROC)."""
|
||||||
|
|
||||||
|
obv: float
|
||||||
|
obv_sma_20: float
|
||||||
|
volume_roc_5: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class SupportResistanceIndicators:
|
||||||
|
"""Support/Resistance levels (Fibonacci, Pivot Points)."""
|
||||||
|
|
||||||
|
fib_236: float
|
||||||
|
fib_382: float
|
||||||
|
fib_618: float
|
||||||
|
pivot_point: float
|
||||||
|
resistance_1: float
|
||||||
|
support_1: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MarketRegimeIndicators:
|
||||||
|
"""Market regime indicators (CCI, Williams %R)."""
|
||||||
|
|
||||||
|
cci_20: float
|
||||||
|
williams_r_14: float
|
||||||
|
194
poetry.lock
generated
194
poetry.lock
generated
@ -1,4 +1,4 @@
|
|||||||
# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotated-types"
|
name = "annotated-types"
|
||||||
@ -70,6 +70,27 @@ charset-normalizer = ["charset-normalizer"]
|
|||||||
html5lib = ["html5lib"]
|
html5lib = ["html5lib"]
|
||||||
lxml = ["lxml"]
|
lxml = ["lxml"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "build"
|
||||||
|
version = "1.3.0"
|
||||||
|
description = "A simple, correct Python build frontend"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "build-1.3.0-py3-none-any.whl", hash = "sha256:7145f0b5061ba90a1500d60bd1b13ca0a8a4cebdd0cc16ed8adf1c0e739f43b4"},
|
||||||
|
{file = "build-1.3.0.tar.gz", hash = "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
colorama = {version = "*", markers = "os_name == \"nt\""}
|
||||||
|
packaging = ">=19.1"
|
||||||
|
pyproject_hooks = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
uv = ["uv (>=0.1.18)"]
|
||||||
|
virtualenv = ["virtualenv (>=20.11) ; python_version < \"3.10\"", "virtualenv (>=20.17) ; python_version >= \"3.10\" and python_version < \"3.14\"", "virtualenv (>=20.31) ; python_version >= \"3.14\""]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2025.10.5"
|
version = "2025.10.5"
|
||||||
@ -290,7 +311,7 @@ description = "Cross-platform colored terminal text."
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "platform_system == \"Windows\" or sys_platform == \"win32\""
|
markers = "platform_system == \"Windows\" or sys_platform == \"win32\" or os_name == \"nt\""
|
||||||
files = [
|
files = [
|
||||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
@ -326,6 +347,88 @@ dev = ["charset_normalizer (>=3.3.2,<4.0)", "coverage (>=6.4.1,<7.0)", "cryptogr
|
|||||||
extra = ["lxml_html_clean", "markdownify (>=1.1.0)", "readability-lxml (>=0.8.1)"]
|
extra = ["lxml_html_clean", "markdownify (>=1.1.0)", "readability-lxml (>=0.8.1)"]
|
||||||
test = ["charset_normalizer (>=3.3.2,<4.0)", "cryptography (>=42.0.5,<43.0)", "fastapi (==0.110.0)", "httpx (==0.23.1)", "proxy.py (>=2.4.3,<3.0)", "pytest (>=8.1.1,<9.0)", "pytest-asyncio (>=0.23.6,<1.0)", "pytest-trio (>=0.8.0,<1.0)", "python-multipart (>=0.0.9,<1.0)", "trio (>=0.25.0,<1.0)", "trustme (>=1.1.0,<2.0)", "typing_extensions", "uvicorn (>=0.29.0,<1.0)", "websockets (>=12.0,<13.0)"]
|
test = ["charset_normalizer (>=3.3.2,<4.0)", "cryptography (>=42.0.5,<43.0)", "fastapi (==0.110.0)", "httpx (==0.23.1)", "proxy.py (>=2.4.3,<3.0)", "pytest (>=8.1.1,<9.0)", "pytest-asyncio (>=0.23.6,<1.0)", "pytest-trio (>=0.8.0,<1.0)", "python-multipart (>=0.0.9,<1.0)", "trio (>=0.25.0,<1.0)", "trustme (>=1.1.0,<2.0)", "typing_extensions", "uvicorn (>=0.29.0,<1.0)", "websockets (>=12.0,<13.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cython"
|
||||||
|
version = "3.1.4"
|
||||||
|
description = "The Cython compiler for writing C extensions in the Python language."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:523110241408ef6511d897e9cebbdffb99120ac82ef3aea89baacce290958f93"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd34f960c3809fa2a7c3487ce9b3cb2c5bbc5ae2107f073a1a51086885958881"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90842e7fb8cddfd173478670297f6a6b3df090e029a31ea6ce93669030e67b81"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c88234303e2c15a5a88ae21c99698c7195433280b049aa2ad0ace906e6294dab"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f06b037f7c244dda9fc38091e87a68498c85c7c27ddc19aa84b08cf42a8a84a"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1aba748e9dcb9c0179d286cdb20215246c46b69cf227715e46287dcea8de7372"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:297b6042d764f68dc6213312578ef4b69310d04c963f94a489914efbf44ab133"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2ecf927e73bde50043d3a9fe3159f834b0e642b97e60a21018439fd25d344888"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-win32.whl", hash = "sha256:3d940d603f85732627795518f9dba8fa63080d8221bb5f477c7a156ee08714ad"},
|
||||||
|
{file = "cython-3.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:1e0671be9859bb313d8df5ca9b9c137e384f1e025831c58cee9a839ace432d3c"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d1d7013dba5fb0506794d4ef8947ff5ed021370614950a8d8d04e57c8c84499e"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eed989f5c139d6550ef2665b783d86fab99372590c97f10a3c26c4523c5fce9e"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3df3beb8b024dfd73cfddb7f2f7456751cebf6e31655eed3189c209b634bc2f2"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f8354703f1168e1aaa01348940f719734c1f11298be333bdb5b94101d49677c0"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a928bd7d446247855f54f359057ab4a32c465219c8c1e299906a483393a59a9e"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c233bfff4cc7b9d629eecb7345f9b733437f76dc4441951ec393b0a6e29919fc"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e9691a2cbc2faf0cd819108bceccf9bfc56c15a06d172eafe74157388c44a601"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ada319207432ea7c6691c70b5c112d261637d79d21ba086ae3726fedde79bfbf"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-win32.whl", hash = "sha256:dae81313c28222bf7be695f85ae1d16625aac35a0973a3af1e001f63379440c5"},
|
||||||
|
{file = "cython-3.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:60d2f192059ac34c5c26527f2beac823d34aaa766ef06792a3b7f290c18ac5e2"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0d26af46505d0e54fe0f05e7ad089fd0eed8fa04f385f3ab88796f554467bcb9"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66ac8bb5068156c92359e3f0eefa138c177d59d1a2e8a89467881fa7d06aba3b"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2e42714faec723d2305607a04bafb49a48a8d8f25dd39368d884c058dbcfbc"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0fd655b27997a209a574873304ded9629de588f021154009e8f923475e2c677"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9def7c41f4dc339003b1e6875f84edf059989b9c7f5e9a245d3ce12c190742d9"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:196555584a8716bf7e017e23ca53e9f632ed493f9faa327d0718e7551588f55d"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7fff0e739e07a20726484b8898b8628a7b87acb960d0fc5486013c6b77b7bb97"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2754034fa10f95052949cd6b07eb2f61d654c1b9cfa0b17ea53a269389422e8"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-win32.whl", hash = "sha256:2e0808ff3614a1dbfd1adfcbff9b2b8119292f1824b3535b4a173205109509f8"},
|
||||||
|
{file = "cython-3.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:f262b32327b6bce340cce5d45bbfe3972cb62543a4930460d8564a489f3aea12"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ab549d0fc187804e0f14fc4759e4b5ad6485ffc01554b2f8b720cc44aeb929cd"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:52eae5d9bcc515441a436dcae2cbadfd00c5063d4d7809bd0178931690c06a76"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6f06345cfa583dd17fff1beedb237853689b85aa400ea9e0db7e5265f3322d15"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f5d915556c757212cb8ddd4e48c16f2ab481dbb9a76f5153ab26f418c3537eb5"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c3f3bb603f28b3c1df66baaa5cdbf6029578552b458f1d321bae23b87f6c3199"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7aff230893ee1044e7bc98d313c034ead70a3dd54d4d22e89ca1734540d94084"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8e83f114c04f72f85591ddb0b28f08ab2e40d250c26686d6509c0f70a9e2ca34"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8096394960d38b793545753b73781bc0ec695f0b8c22454431704b297e296045"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-win32.whl", hash = "sha256:4e7c726ac753ca1a5aa30286cbadcd10ed4b4312ea710a8a16bb908d41e9c059"},
|
||||||
|
{file = "cython-3.1.4-cp313-cp313-win_amd64.whl", hash = "sha256:f2ee2bb77943044f301cec04d0b51d8e3810507c9c250d6cd079a3e2d6ba88f2"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c7258739d5560918741cb040bd85ba7cc2f09d868de9116a637e06714fec1f69"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b2d522ee8d3528035e247ee721fb40abe92e9ea852dc9e48802cec080d5de859"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a4e0560baeb56c29d7d8d693a050dd4d2ed922d8d7c66f5c5715c6f2be84e903"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4223cacc81cba0df0f06f79657c5d6286e153b9a9b989dad1cdf4666f618c073"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ff4d1f159edee6af38572318681388fbd6448b0d08b9a47494aaf0b698e93394"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2537c53071a9a124e0bc502a716e1930d9bb101e94c26673016cf1820e4fdbd1"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:85416717c529fb5ccf908464657a5187753e76d7b6ffec9b1c2d91544f6c3628"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:18882e2f5c0e0c25f9c44f16f2fb9c48f33988885c5f9eae2856f10c6f089ffa"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-win32.whl", hash = "sha256:8ef8deadc888eaf95e5328fc176fb6c37bccee1213f07517c6ea55b5f817c457"},
|
||||||
|
{file = "cython-3.1.4-cp314-cp314-win_amd64.whl", hash = "sha256:acb99ddec62ba1ea5de0e0087760fa834ec42c94f0488065a4f1995584e8e94e"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:949074a2445c8fe2b84e81b6cf9c23b30b92e853ad05689457d6735acb2ca738"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:533970de5d96ca9ba207aa096caa883e2365ce7d41f0531f070292842b4ba97a"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:078e4e48d3867abf1ba11ca6bd2d62974a326ef2c0d139daa6691f5e01a691c5"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c162d63c2a7636864bcee0f333d974ece325d4fbc33e75d38886926e1cc997a1"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e10357ea1acc27b42d83aaeb14cd94587b515806a41227a0100028d45140d753"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:71435feecca14f4de4b3a6b3828d8b1ae4a3b535e53597c32d5f22bc87f3d2bb"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d24c8a4fb10c089ec45fcc1c44f73df5b4228c95f20539cc4aade7a8933be31c"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2ccbd6db72f864c6717dcc62e44673e81cfe38984277748818cbe427f461573c"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-win32.whl", hash = "sha256:94fd9a7807fdd7cffe82c0b7167a9f5fcf0e7c6ef518d89bed66430bd9107854"},
|
||||||
|
{file = "cython-3.1.4-cp38-cp38-win_amd64.whl", hash = "sha256:b47a82cfbc8e6a87143f02e1b33b7a0332bd1b83b668cb41ebcb5e4f9a39bc09"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b95d2303ee54cf469f7c61aa94ef46c195d42e75a76881b9e33770bcf6c0a5c6"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fc723ffca257beebe42c8e2dcb2b9771957b752d6f42684f17ca1d2a4346b21"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1fb5060dd0c89f5c64002a0c44c2fcb5d066d119e2ae4d1bfa2c6482333dd42a"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:077cc5881da9b48cc7b7f7952faedcea0ad9c3fcb9ba9f5fb89fdb5ded07dd70"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:33da3c03797f7b7fde371a05f9e0d63eca679875c1c75e01066893eff2ec2f12"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:daf1bde7af8202f52cfd51625a5c48de55de27786392e38a429bfe8b9a16161f"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3371af4af1aae0d46c10f8e3c1edff0361f03a5687081c8b36f61678545caff3"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d4e1115c6b4b848ade9d76a4e3f72c7bb2b7e7a935fcbda56f6032f50e079999"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-win32.whl", hash = "sha256:1b59709bcec2f38e447e53c51a20caee8c30911d4025dd3d102835f3f10b7bef"},
|
||||||
|
{file = "cython-3.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:006e2a175ba9898a7f1551e6c7c4cafd8eb9b42e53d1dfe4308caba9e8453cc3"},
|
||||||
|
{file = "cython-3.1.4-py3-none-any.whl", hash = "sha256:d194d95e4fa029a3f6c7d46bdd16d973808c7ea4797586911fdb67cb98b1a2c6"},
|
||||||
|
{file = "cython-3.1.4.tar.gz", hash = "sha256:9aefefe831331e2d66ab31799814eae4d0f8a2d246cbaaaa14d1be29ef777683"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "decorator"
|
name = "decorator"
|
||||||
version = "5.2.1"
|
version = "5.2.1"
|
||||||
@ -734,6 +837,18 @@ files = [
|
|||||||
{file = "numpy-2.3.4.tar.gz", hash = "sha256:a7d018bfedb375a8d979ac758b120ba846a7fe764911a64465fd87b8729f4a6a"},
|
{file = "numpy-2.3.4.tar.gz", hash = "sha256:a7d018bfedb375a8d979ac758b120ba846a7fe764911a64465fd87b8729f4a6a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packaging"
|
||||||
|
version = "25.0"
|
||||||
|
description = "Core utilities for Python packages"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"},
|
||||||
|
{file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pandas"
|
name = "pandas"
|
||||||
version = "2.3.3"
|
version = "2.3.3"
|
||||||
@ -1169,6 +1284,18 @@ files = [
|
|||||||
doc = ["sphinx (>=6.1.3,<6.2.0)", "sphinx_rtd_theme (>=1.2.0,<1.3.0)"]
|
doc = ["sphinx (>=6.1.3,<6.2.0)", "sphinx_rtd_theme (>=1.2.0,<1.3.0)"]
|
||||||
test = ["beautifulsoup4", "flake8", "pytest", "pytest-cov"]
|
test = ["beautifulsoup4", "flake8", "pytest", "pytest-cov"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyproject-hooks"
|
||||||
|
version = "1.2.0"
|
||||||
|
description = "Wrappers to call pyproject.toml-based build backend hooks."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913"},
|
||||||
|
{file = "pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-dateutil"
|
name = "python-dateutil"
|
||||||
version = "2.9.0.post0"
|
version = "2.9.0.post0"
|
||||||
@ -1420,6 +1547,67 @@ pure-eval = "*"
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
|
tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ta-lib"
|
||||||
|
version = "0.6.7"
|
||||||
|
description = "Python wrapper for TA-Lib"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:98ca46298595196976d685e3628d28b866bece556c1a11cc1a950260931748f2"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:79e0d15db755d4c4c34216945467e2c0c0a0768bb6cd5ced09c331deb54c7702"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:35ba7ce42cc5dcdd0ad9dee6d4b9fd9025538ffd00865b1be81d5b56e44da377"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a04fdc1bc77093098557d2af8ba7ac6cf9fdbe33c9224471f8e0c066c9e6dfa0"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:79efa70190cee4cb3440a57ce8e7897fb0939890ee35f1564f01ea313319ddba"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c6b86adaeb801248f4043fce58c560655179969c9133c16763687fb28c2a3bdc"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-win32.whl", hash = "sha256:3123ffe82a5677b79085b2206b4ee370b13c6ba7594818277734326ecace21ee"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:39c60c48a5fb62c890f1cb3faa165dfe66e0e9c7e49bb3b43b3c7843868f1fb4"},
|
||||||
|
{file = "ta_lib-0.6.7-cp310-cp310-win_arm64.whl", hash = "sha256:250b9047dc52c6d9fa812aebf86495537dcf4f24d84b6bd8fbae32c7ee2f110e"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:f3f5fda59669203d2f890606eb0a146bc4682ece9bfd77dacf5bc749b91c38d6"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:293c92b4b5b58174c7689b7349c8be104886ee34245e8354016ba6849cf628c1"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:ea4ea820dad59415a5cab2ab86b3529ea1ca230230fb3d4036f2273c4345140f"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:348c615e8c5fc9461cb241616dc7953977fef7004f2cf1d5ff009e43edf39759"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1118a0957c8b3d26dd4a0d49c49c7fda61794aa04b39b652d258b65a0f3c0869"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:028defb19a9042e2876fd269aee489b300029cc5c58a1cb5a21f31d7495ad728"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-win32.whl", hash = "sha256:ef3bb9ba7ed8e8f112a7c60e386a41b260c77c126613a6a01d393681c32a60dc"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-win_amd64.whl", hash = "sha256:681517c82d4803bf5940524d2e046bbc55b86a82c449f7c70b1bfce93cc5828e"},
|
||||||
|
{file = "ta_lib-0.6.7-cp311-cp311-win_arm64.whl", hash = "sha256:46214874dfbee6f3b071737df1ddf0f7ccfbb7764cf612a2f3d74942d308cc64"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-macosx_13_0_x86_64.whl", hash = "sha256:4c28957ab9e6f26e4ffc8c9354dc2d3f920a16b3516ff010888cded8fe258b14"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:fb49c2388238bd176c7e4589979ab3d58f9876ca144cd6551273c19d9e6aa1eb"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:d9d2352c4b12bb221d599b1730fca5748b9259ff29aa19c4b1a368d87c54656d"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:a07967a28066a12b8fb94c97fc3bd3c563f04432f2383703763f53bc94aba92b"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1843491cb19de376366e490c9ea60d43408162ddd9675c006cec03eeca32063d"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76e5b89bc9be6f1721a65384c8c33bb384a17f29ec22490dd57db49ed185cd5b"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-win32.whl", hash = "sha256:411b4d05e976c9de4993c3b578aaadec353478287e886a0b72db881e0abba43d"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-win_amd64.whl", hash = "sha256:1cb66ca90d954a5bf3dbfad2679ba14e83f7d2ee72feeb51c1187efb88ef282c"},
|
||||||
|
{file = "ta_lib-0.6.7-cp312-cp312-win_arm64.whl", hash = "sha256:0ff9490faaaba625ffc2cfd520764067cd6255e663dd8d020cbcaa33870c8a56"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:dfe4a7fb1c6a6452e7704b0baa3633c03241d616515d07365bc9114c5b85be87"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d3fd2175bdfeb5822b7c8364a0fcdc8eb4c07af9593f84480a10a4cf827d9266"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:167a4b75a8c723d0b995269e67270d9cdfa22bed59957f0386cea0fe82b41c33"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:8640e9e12a4bcddf5f7e3460430f259fea16c27eeab13481ff16a6964db1e58b"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f69f22a561f10457b86e09bb8700c36eeafad1944010c7cc894bba8be827cd9"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ef03e89b39f0e5d8ab74a9d2a2537ce202bcf622ed190d8d1c0077cf9cb7c11b"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-win32.whl", hash = "sha256:3af4953d128676488a58df42b61bcaace669f83110f54d2dd2e866105093f597"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-win_amd64.whl", hash = "sha256:213423db3afddc9541ab54e8841bcf5f6a6b5a41625d70bd1544e58952a8fe2c"},
|
||||||
|
{file = "ta_lib-0.6.7-cp313-cp313-win_arm64.whl", hash = "sha256:ffc54a335c0e7ea69a4217ab8e93cada8871e591badb95fd7f2a0430eaa59825"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:0bbb20f2653397c28fddafbd23b5ee98b64a3c60e7d11fe67eae7435f464896c"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:e6ddceae8193ca4337cf70698fd2f58b341d073f0c5a9d49c1ba5d289dc1d6c9"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:07d20576d12dd75f9823212d8aa297bdb50f1c88749ccc4d3b44a771ee74fb99"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:c7d1ba210ac9f8f211b3cace3c8e2fe6d65a8ff729af33133efac8910f239a44"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:79e8d8d1e9d7fdf0ce784c7a11dfef4dc1c5010f82bb3b5bf97c36eb399eefa8"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0bb487f39c333e93226a796eec8c8fbfdea1275bb8415790601967aa3280fe04"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-win32.whl", hash = "sha256:3c56e43aede6f8514045102d3d0bae52d8752aaac559c34fee5c447fd1cbf90a"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:f6e62d9e2d2d7b3825030a94eb82741299825d6d90016b2fc01c96610a8853f9"},
|
||||||
|
{file = "ta_lib-0.6.7-cp39-cp39-win_arm64.whl", hash = "sha256:da66c7c6feda7bdc9ece5ecb518d872339f764d890d1c6e71b98bf4ad37deb07"},
|
||||||
|
{file = "ta_lib-0.6.7.tar.gz", hash = "sha256:d702cbb20ab34d6d6c46bef87a1bd4bfeae0cc0ab65cbdf1d23dd392ce110d69"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
build = "*"
|
||||||
|
cython = "*"
|
||||||
|
numpy = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toolz"
|
name = "toolz"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -1647,4 +1835,4 @@ repair = ["scipy (>=1.6.3)"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = ">=3.13"
|
python-versions = ">=3.13"
|
||||||
content-hash = "f8ab199e4a4efc383caa5691f31314d4cdecc6564e120b4024ce3eb1711d00f5"
|
content-hash = "c9a5936e446cf6234585a330d4fc3888dd4a8c8db505bbc9e78d454cfe864569"
|
||||||
|
@ -15,7 +15,8 @@ dependencies = [
|
|||||||
"yfinance (>=0.2.66,<0.3.0)",
|
"yfinance (>=0.2.66,<0.3.0)",
|
||||||
"ipython (>=9.6.0,<10.0.0)",
|
"ipython (>=9.6.0,<10.0.0)",
|
||||||
"pandas-market-calendars (>=5.1.1,<6.0.0)",
|
"pandas-market-calendars (>=5.1.1,<6.0.0)",
|
||||||
"sqlmodel (>=0.0.27,<0.0.28)"
|
"sqlmodel (>=0.0.27,<0.0.28)",
|
||||||
|
"ta-lib (>=0.6.7,<0.7.0)"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user