eetc-utils 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eetc-utils
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: EETC Utils Library
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "eetc-utils"
7
- version = "1.2.0"
7
+ version = "1.3.0"
8
8
  description = "EETC Utils Library"
9
9
  authors = [
10
10
  "East Empire Trading Company <eastempiretradingcompany2019@gmail.com>",
@@ -374,3 +374,104 @@ class EETCDataClient:
374
374
 
375
375
  if response.status_code not in [200, 201]:
376
376
  response.raise_for_status()
377
+
378
+ def get_roguetrader_signals(
379
+ self,
380
+ date: Optional[str] = None,
381
+ symbol: Optional[str] = None,
382
+ as_json: bool = False,
383
+ ) -> Union[pd.DataFrame, List[Dict]]:
384
+ """
385
+ Retrieve RogueTrader signals from the EETC Data Hub via the
386
+ `/roguetrader-signals` API.
387
+
388
+ This endpoint returns eetc-roguetrader generated signals data
389
+ with optional filtering. Filters can be combined to narrow
390
+ down results (e.g., by date and symbol).
391
+
392
+ :param date: Signal generation date in format "yyyy-mm-dd".
393
+ :param symbol: Ticker symbol of the instrument (e.g., "AAPL").
394
+ :param as_json: If True, returns raw JSON list; if False
395
+ (default), returns pandas DataFrame.
396
+ :return: RogueTrader signals data as pandas DataFrame (default)
397
+ or list of dicts (if as_json=True).
398
+ :raises requests.HTTPError: If the API request fails.
399
+ """
400
+
401
+ url = f"{self.base_url}/roguetrader-signals/"
402
+ params = {
403
+ "date": date,
404
+ "symbol": symbol,
405
+ }
406
+ params = {k: v for k, v in params.items() if v is not None}
407
+
408
+ response = self._send_http_request(url, params)
409
+ data = response.json()
410
+
411
+ return data if as_json else pd.json_normalize(data)
412
+
413
+ def save_roguetrader_signals(self, signals: List[Dict[str, Any]]) -> None:
414
+ """
415
+ Save one or multiple eetc-roguetrader signals to the EETC Data
416
+ Hub.
417
+
418
+ :param signals: List of signal dictionaries. Each signal should
419
+ contain:
420
+ - date (str): Signal generation date (e.g., "2024-01-15")
421
+ - symbol (str): Ticker symbol (e.g., "SPY")
422
+ - previous_close (float): Previous day's closing price
423
+ - open_price (float): Opening price
424
+ - open_gap (float): Gap percentage
425
+ - atm_strike (int): At-the-money strike price
426
+ - atm_iv (float): At-the-money implied volatility
427
+ - implied_daily_move_pct (float): Expected daily move %
428
+ - atm_greeks (dict): ATM option Greeks
429
+ - vix_previous_close (float): Previous VIX close
430
+ - vix_at_calculation (float): VIX at calculation time
431
+ - vix_change_pct (float): VIX change percentage
432
+ - signals (list): List of signal values
433
+ - aggregate_gex (float): Aggregate gamma exposure
434
+ - zero_gamma_level (float): Zero gamma price level
435
+ - gex_regime (str): GEX regime ("positive" or "negative")
436
+ - trading_allowed (bool): Whether trading is allowed
437
+ - halt_reason (str, optional): Reason for trading halt
438
+
439
+ Example:
440
+ >>> client.save_roguetrader_signals([{
441
+ ... "date": "2024-01-15",
442
+ ... "symbol": "SPY",
443
+ ... "previous_close": 450.25,
444
+ ... "open_price": 451.00,
445
+ ... "open_gap": 0.17,
446
+ ... "atm_strike": 450,
447
+ ... "atm_iv": 0.15,
448
+ ... "implied_daily_move_pct": 1.2,
449
+ ... "atm_greeks": {"delta": 0.5, "gamma": 0.02},
450
+ ... "vix_previous_close": 14.5,
451
+ ... "vix_at_calculation": 15.2,
452
+ ... "vix_change_pct": 4.83,
453
+ ... "signals": [{"signal": 13.12}],
454
+ ... "aggregate_gex": 1250000.0,
455
+ ... "zero_gamma_level": 448.5,
456
+ ... "gex_regime": "positive",
457
+ ... "trading_allowed": True,
458
+ ... "halt_reason": None
459
+ ... }])
460
+
461
+ :raises requests.HTTPError: If the API request fails
462
+ (non-200/201 status).
463
+ """
464
+
465
+ url = f"{self.base_url}/roguetrader-signals/"
466
+
467
+ response = requests.post(
468
+ url,
469
+ json=signals,
470
+ headers={
471
+ "Content-Type": "application/json",
472
+ "EETC-API-Key": self.api_key,
473
+ },
474
+ )
475
+
476
+ if response.status_code not in [200, 201]:
477
+ response.raise_for_status()
@@ -114,7 +114,7 @@ def calculate_optimal_leverage_kelly(
114
114
  if use_garch:
115
115
  # use GARCH function to get annualized volatility
116
116
  annualized_volatility = garch_annualized_volatility(df)
117
- annualized_variance = annualized_volatility ** 2
117
+ annualized_variance = annualized_volatility**2
118
118
  else:
119
119
  # simple historical variance
120
120
  daily_variance = df["log_return"].var()
File without changes
File without changes