vn6295337 commited on
Commit
052525e
·
1 Parent(s): 7531716

chore: Remove dead Tradier integration

Browse files

fetch_tradier_implied_volatility was never called and no Tradier key
has ever been provisioned; volatility is served by Yahoo + FRED
(+ Alpha Vantage when keyed). Removes the fetcher, config, and
.env.example entry.

.env.example CHANGED
@@ -18,8 +18,6 @@ FRED_VIX_API_KEY=your_fred_api_key
18
  # Alpha Vantage (implied volatility; free tier is 25 req/day)
19
  ALPHA_VANTAGE_API_KEY=your_alphavantage_api_key
20
 
21
- # Tradier (options data for volatility basket)
22
- TRADIER_API_KEY=your_tradier_api_key
23
 
24
  # BLS - Bureau of Labor Statistics (macro basket)
25
  BLS_API_KEY=your_bls_api_key
 
18
  # Alpha Vantage (implied volatility; free tier is 25 req/day)
19
  ALPHA_VANTAGE_API_KEY=your_alphavantage_api_key
20
 
 
 
21
 
22
  # BLS - Bureau of Labor Statistics (macro basket)
23
  BLS_API_KEY=your_bls_api_key
mcp-servers/volatility-basket/server.py CHANGED
@@ -52,14 +52,10 @@ server = Server("volatility-basket")
52
  # API Keys (optional - enables authoritative sources)
53
  FRED_API_KEY = os.getenv("FRED_API_KEY") or os.getenv("FRED_VIX_API_KEY") # Get free key: https://fred.stlouisfed.org/docs/api/api_key.html
54
  ALPHA_VANTAGE_KEY = os.getenv("ALPHA_VANTAGE_API_KEY") # Get free key: https://www.alphavantage.co/support/#api-key
55
- TRADIER_API_KEY = os.getenv("TRADIER_API_KEY") # Get free key: https://developer.tradier.com/
56
 
57
  # Alpha Vantage API configuration (Secondary for Beta, Historical Volatility)
58
  ALPHA_VANTAGE_BASE_URL = "https://www.alphavantage.co/query"
59
 
60
- # Tradier API configuration (Primary for Implied Volatility)
61
- TRADIER_BASE_URL = "https://api.tradier.com/v1"
62
-
63
  # Yahoo Finance requires browser-like headers
64
  YAHOO_HEADERS = {
65
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
@@ -734,127 +730,6 @@ async def fetch_alpha_vantage_historical_volatility(ticker: str, period_days: in
734
  return None
735
 
736
 
737
- # ============================================================
738
- # TRADIER FETCHERS (Primary/Secondary for Implied Volatility)
739
- # ============================================================
740
-
741
- async def fetch_tradier_implied_volatility(ticker: str) -> Optional[dict]:
742
- """
743
- Fetch implied volatility from Tradier options chain.
744
- Provides stock-specific IV from ATM options.
745
-
746
- API: https://developer.tradier.com/
747
- Requires free account creation.
748
- """
749
- if not TRADIER_API_KEY:
750
- return None
751
-
752
- try:
753
- async with httpx.AsyncClient() as client:
754
- headers = {
755
- "Authorization": f"Bearer {TRADIER_API_KEY}",
756
- "Accept": "application/json"
757
- }
758
-
759
- # First get current quote for ATM strike
760
- quote_url = f"{TRADIER_BASE_URL}/markets/quotes"
761
- quote_params = {"symbols": ticker.upper()}
762
- quote_resp = await client.get(quote_url, params=quote_params, headers=headers, timeout=10)
763
- quote_data = quote_resp.json()
764
-
765
- quotes = quote_data.get("quotes", {}).get("quote", {})
766
- if isinstance(quotes, list):
767
- quotes = quotes[0] if quotes else {}
768
-
769
- current_price = quotes.get("last", 0) or quotes.get("close", 0)
770
- if not current_price:
771
- return None
772
-
773
- # Get options expirations
774
- exp_url = f"{TRADIER_BASE_URL}/markets/options/expirations"
775
- exp_params = {"symbol": ticker.upper()}
776
- exp_resp = await client.get(exp_url, params=exp_params, headers=headers, timeout=10)
777
- exp_data = exp_resp.json()
778
-
779
- expirations = exp_data.get("expirations", {}).get("date", [])
780
- if not expirations:
781
- return None
782
-
783
- # Use nearest expiration
784
- nearest_exp = expirations[0] if isinstance(expirations, list) else expirations
785
-
786
- # Get options chain
787
- chain_url = f"{TRADIER_BASE_URL}/markets/options/chains"
788
- chain_params = {
789
- "symbol": ticker.upper(),
790
- "expiration": nearest_exp,
791
- "greeks": "true"
792
- }
793
- chain_resp = await client.get(chain_url, params=chain_params, headers=headers, timeout=10)
794
- chain_data = chain_resp.json()
795
-
796
- options = chain_data.get("options", {}).get("option", [])
797
- if not options:
798
- return None
799
-
800
- # Filter calls and find ATM
801
- calls = [o for o in options if o.get("option_type") == "call"]
802
- if not calls:
803
- return None
804
-
805
- # Find ATM call (closest to current price)
806
- atm_call = min(calls, key=lambda x: abs(x.get("strike", 0) - current_price))
807
-
808
- # Get IV from greeks
809
- greeks = atm_call.get("greeks", {})
810
- iv = greeks.get("mid_iv", 0) or greeks.get("ask_iv", 0) or greeks.get("bid_iv", 0)
811
-
812
- if not iv:
813
- # Fallback to smv_vol if available
814
- iv = greeks.get("smv_vol", 0)
815
-
816
- if not iv:
817
- return None
818
-
819
- iv_pct = iv * 100 # Convert to percentage
820
-
821
- # Interpretation
822
- if iv_pct < 25:
823
- interpretation = "Low IV - Market expects limited price movement"
824
- swot_impact = "OPPORTUNITY"
825
- elif iv_pct < 40:
826
- interpretation = "Moderate IV - Normal expected movement"
827
- swot_impact = "NEUTRAL"
828
- elif iv_pct < 60:
829
- interpretation = "High IV - Market expects significant movement"
830
- swot_impact = "THREAT"
831
- else:
832
- interpretation = "Very high IV - Extreme movement expected (earnings, event)"
833
- swot_impact = "THREAT"
834
-
835
- # Use quote trade_date if available, else today
836
- trade_date = quote.get("trade_date", datetime.now().strftime("%Y-%m-%d"))
837
- if isinstance(trade_date, str) and "T" in trade_date:
838
- trade_date = trade_date.split("T")[0]
839
-
840
- return {
841
- "metric": "Implied Volatility",
842
- "ticker": ticker.upper(),
843
- "value": round(iv_pct, 2),
844
- "unit": "%",
845
- "strike": atm_call.get("strike"),
846
- "expiration": nearest_exp,
847
- "interpretation": interpretation,
848
- "swot_category": swot_impact,
849
- "source": "Tradier",
850
- "as_of": trade_date
851
- }
852
-
853
- except Exception as e:
854
- logger.error(f"Tradier IV fetch error for {ticker}: {e}")
855
- return None
856
-
857
-
858
  # ============================================================
859
  # MULTI-SOURCE AGGREGATOR
860
  # ============================================================
 
52
  # API Keys (optional - enables authoritative sources)
53
  FRED_API_KEY = os.getenv("FRED_API_KEY") or os.getenv("FRED_VIX_API_KEY") # Get free key: https://fred.stlouisfed.org/docs/api/api_key.html
54
  ALPHA_VANTAGE_KEY = os.getenv("ALPHA_VANTAGE_API_KEY") # Get free key: https://www.alphavantage.co/support/#api-key
 
55
 
56
  # Alpha Vantage API configuration (Secondary for Beta, Historical Volatility)
57
  ALPHA_VANTAGE_BASE_URL = "https://www.alphavantage.co/query"
58
 
 
 
 
59
  # Yahoo Finance requires browser-like headers
60
  YAHOO_HEADERS = {
61
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
 
730
  return None
731
 
732
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
733
  # ============================================================
734
  # MULTI-SOURCE AGGREGATOR
735
  # ============================================================
mcp_client.py CHANGED
@@ -356,7 +356,7 @@ async def call_volatility_mcp(ticker: str) -> dict:
356
 
357
 
358
  async def call_volatility_all_sources_mcp(ticker: str) -> dict:
359
- """Fetch volatility from ALL sources (Yahoo + Alpha Vantage + Tradier)."""
360
  return await call_mcp_server(
361
  "volatility-basket",
362
  "get_all_sources_volatility",
 
356
 
357
 
358
  async def call_volatility_all_sources_mcp(ticker: str) -> dict:
359
+ """Fetch volatility from ALL sources (Yahoo + Alpha Vantage)."""
360
  return await call_mcp_server(
361
  "volatility-basket",
362
  "get_all_sources_volatility",