mcli-framework 7.3.1__py3-none-any.whl → 7.5.0__py3-none-any.whl
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.
Potentially problematic release.
This version of mcli-framework might be problematic. Click here for more details.
- mcli/app/commands_cmd.py +741 -0
- mcli/lib/auth/aws_manager.py +9 -64
- mcli/lib/auth/azure_manager.py +9 -64
- mcli/lib/auth/credential_manager.py +70 -1
- mcli/lib/auth/gcp_manager.py +11 -64
- mcli/ml/dashboard/app.py +6 -39
- mcli/ml/dashboard/app_integrated.py +288 -117
- mcli/ml/dashboard/app_supabase.py +8 -57
- mcli/ml/dashboard/app_training.py +10 -12
- mcli/ml/dashboard/common.py +167 -0
- mcli/ml/dashboard/overview.py +378 -0
- mcli/ml/dashboard/pages/cicd.py +4 -4
- mcli/ml/dashboard/pages/debug_dependencies.py +406 -0
- mcli/ml/dashboard/pages/gravity_viz.py +783 -0
- mcli/ml/dashboard/pages/monte_carlo_predictions.py +555 -0
- mcli/ml/dashboard/pages/predictions_enhanced.py +4 -2
- mcli/ml/dashboard/pages/scrapers_and_logs.py +25 -9
- mcli/ml/dashboard/pages/test_portfolio.py +54 -4
- mcli/ml/dashboard/pages/trading.py +80 -26
- mcli/ml/dashboard/streamlit_extras_utils.py +297 -0
- mcli/ml/dashboard/styles.py +55 -0
- mcli/ml/dashboard/utils.py +7 -0
- mcli/ml/dashboard/warning_suppression.py +34 -0
- mcli/ml/database/session.py +169 -16
- mcli/ml/predictions/monte_carlo.py +428 -0
- mcli/ml/trading/alpaca_client.py +82 -18
- mcli/self/self_cmd.py +182 -737
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/METADATA +2 -3
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/RECORD +33 -87
- mcli/__init__.py +0 -160
- mcli/__main__.py +0 -14
- mcli/app/__init__.py +0 -23
- mcli/app/model/__init__.py +0 -0
- mcli/app/video/__init__.py +0 -5
- mcli/chat/__init__.py +0 -34
- mcli/lib/__init__.py +0 -0
- mcli/lib/api/__init__.py +0 -0
- mcli/lib/auth/__init__.py +0 -1
- mcli/lib/config/__init__.py +0 -1
- mcli/lib/erd/__init__.py +0 -25
- mcli/lib/files/__init__.py +0 -0
- mcli/lib/fs/__init__.py +0 -1
- mcli/lib/logger/__init__.py +0 -3
- mcli/lib/performance/__init__.py +0 -17
- mcli/lib/pickles/__init__.py +0 -1
- mcli/lib/shell/__init__.py +0 -0
- mcli/lib/toml/__init__.py +0 -1
- mcli/lib/watcher/__init__.py +0 -0
- mcli/ml/__init__.py +0 -16
- mcli/ml/api/__init__.py +0 -30
- mcli/ml/api/routers/__init__.py +0 -27
- mcli/ml/auth/__init__.py +0 -45
- mcli/ml/backtesting/__init__.py +0 -39
- mcli/ml/cli/__init__.py +0 -5
- mcli/ml/config/__init__.py +0 -33
- mcli/ml/configs/__init__.py +0 -16
- mcli/ml/dashboard/__init__.py +0 -12
- mcli/ml/dashboard/components/__init__.py +0 -7
- mcli/ml/dashboard/pages/__init__.py +0 -6
- mcli/ml/data_ingestion/__init__.py +0 -39
- mcli/ml/database/__init__.py +0 -47
- mcli/ml/experimentation/__init__.py +0 -29
- mcli/ml/features/__init__.py +0 -39
- mcli/ml/mlops/__init__.py +0 -33
- mcli/ml/models/__init__.py +0 -94
- mcli/ml/monitoring/__init__.py +0 -25
- mcli/ml/optimization/__init__.py +0 -27
- mcli/ml/predictions/__init__.py +0 -5
- mcli/ml/preprocessing/__init__.py +0 -28
- mcli/ml/scripts/__init__.py +0 -1
- mcli/ml/trading/__init__.py +0 -60
- mcli/ml/training/__init__.py +0 -10
- mcli/mygroup/__init__.py +0 -3
- mcli/public/__init__.py +0 -1
- mcli/public/commands/__init__.py +0 -2
- mcli/self/__init__.py +0 -3
- mcli/workflow/__init__.py +0 -0
- mcli/workflow/daemon/__init__.py +0 -15
- mcli/workflow/dashboard/__init__.py +0 -5
- mcli/workflow/docker/__init__.py +0 -0
- mcli/workflow/file/__init__.py +0 -0
- mcli/workflow/gcloud/__init__.py +0 -1
- mcli/workflow/git_commit/__init__.py +0 -0
- mcli/workflow/interview/__init__.py +0 -0
- mcli/workflow/politician_trading/__init__.py +0 -4
- mcli/workflow/registry/__init__.py +0 -0
- mcli/workflow/repo/__init__.py +0 -0
- mcli/workflow/scheduler/__init__.py +0 -25
- mcli/workflow/search/__init__.py +0 -0
- mcli/workflow/sync/__init__.py +0 -5
- mcli/workflow/videos/__init__.py +0 -1
- mcli/workflow/wakatime/__init__.py +0 -80
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/WHEEL +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/top_level.txt +0 -0
mcli/ml/trading/alpaca_client.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Alpaca Trading API client for executing trades"""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import os
|
|
4
5
|
from datetime import datetime, timedelta
|
|
5
6
|
from decimal import Decimal
|
|
6
7
|
from typing import Dict, List, Optional, Tuple, Union
|
|
@@ -18,6 +19,10 @@ from alpaca.data.historical import StockHistoricalDataClient
|
|
|
18
19
|
from alpaca.data.requests import StockBarsRequest
|
|
19
20
|
from alpaca.data.timeframe import TimeFrame
|
|
20
21
|
from pydantic import BaseModel, Field
|
|
22
|
+
from dotenv import load_dotenv
|
|
23
|
+
|
|
24
|
+
# Load environment variables
|
|
25
|
+
load_dotenv()
|
|
21
26
|
|
|
22
27
|
logger = logging.getLogger(__name__)
|
|
23
28
|
|
|
@@ -81,32 +86,44 @@ class AlpacaTradingClient:
|
|
|
81
86
|
self.trading_client = TradingClient(
|
|
82
87
|
api_key=config.api_key,
|
|
83
88
|
secret_key=config.secret_key,
|
|
84
|
-
paper=config.paper_trading
|
|
85
|
-
base_url=config.base_url
|
|
89
|
+
paper=config.paper_trading
|
|
86
90
|
)
|
|
87
91
|
self.data_client = StockHistoricalDataClient(
|
|
88
92
|
api_key=config.api_key,
|
|
89
|
-
secret_key=config.secret_key
|
|
90
|
-
base_url=config.data_url
|
|
93
|
+
secret_key=config.secret_key
|
|
91
94
|
)
|
|
92
95
|
|
|
93
96
|
def get_account(self) -> Dict:
|
|
94
97
|
"""Get account information"""
|
|
95
98
|
try:
|
|
96
99
|
account = self.trading_client.get_account()
|
|
97
|
-
|
|
100
|
+
|
|
101
|
+
# Build response with safe attribute access
|
|
102
|
+
response = {
|
|
98
103
|
"account_id": account.id,
|
|
99
|
-
"equity": float(account.equity),
|
|
100
|
-
"cash": float(account.cash),
|
|
101
|
-
"buying_power": float(account.buying_power),
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"status": account.status,
|
|
107
|
-
"trading_blocked": account.trading_blocked,
|
|
108
|
-
"pattern_day_trader": account.pattern_day_trader,
|
|
104
|
+
"equity": float(account.equity) if hasattr(account, 'equity') else 0.0,
|
|
105
|
+
"cash": float(account.cash) if hasattr(account, 'cash') else 0.0,
|
|
106
|
+
"buying_power": float(account.buying_power) if hasattr(account, 'buying_power') else 0.0,
|
|
107
|
+
"currency": account.currency if hasattr(account, 'currency') else "USD",
|
|
108
|
+
"status": account.status.value if hasattr(account.status, 'value') else str(account.status),
|
|
109
|
+
"trading_blocked": account.trading_blocked if hasattr(account, 'trading_blocked') else False,
|
|
110
|
+
"pattern_day_trader": account.pattern_day_trader if hasattr(account, 'pattern_day_trader') else False,
|
|
109
111
|
}
|
|
112
|
+
|
|
113
|
+
# Add optional fields that may not exist in all account types
|
|
114
|
+
if hasattr(account, 'portfolio_value'):
|
|
115
|
+
response["portfolio_value"] = float(account.portfolio_value)
|
|
116
|
+
else:
|
|
117
|
+
response["portfolio_value"] = response["equity"]
|
|
118
|
+
|
|
119
|
+
if hasattr(account, 'long_market_value'):
|
|
120
|
+
response["unrealized_pl"] = float(account.long_market_value) - float(account.cash)
|
|
121
|
+
else:
|
|
122
|
+
response["unrealized_pl"] = 0.0
|
|
123
|
+
|
|
124
|
+
response["realized_pl"] = 0.0 # Not always available in paper accounts
|
|
125
|
+
|
|
126
|
+
return response
|
|
110
127
|
except Exception as e:
|
|
111
128
|
logger.error(f"Failed to get account info: {e}")
|
|
112
129
|
raise
|
|
@@ -343,11 +360,58 @@ class AlpacaTradingClient:
|
|
|
343
360
|
raise
|
|
344
361
|
|
|
345
362
|
|
|
346
|
-
def create_trading_client(api_key: str, secret_key: str, paper_trading: bool = True) -> AlpacaTradingClient:
|
|
347
|
-
"""
|
|
363
|
+
def create_trading_client(api_key: str = None, secret_key: str = None, paper_trading: bool = True) -> AlpacaTradingClient:
|
|
364
|
+
"""
|
|
365
|
+
Create a trading client with the given credentials or from environment variables
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
api_key: Alpaca API key (if None, loads from ALPACA_API_KEY env var)
|
|
369
|
+
secret_key: Alpaca secret key (if None, loads from ALPACA_SECRET_KEY env var)
|
|
370
|
+
paper_trading: Whether to use paper trading (default: True)
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
AlpacaTradingClient instance
|
|
374
|
+
"""
|
|
375
|
+
# Load from environment if not provided
|
|
376
|
+
if api_key is None:
|
|
377
|
+
api_key = os.getenv("ALPACA_API_KEY")
|
|
378
|
+
if secret_key is None:
|
|
379
|
+
secret_key = os.getenv("ALPACA_SECRET_KEY")
|
|
380
|
+
|
|
381
|
+
if not api_key or not secret_key:
|
|
382
|
+
raise ValueError(
|
|
383
|
+
"Alpaca API credentials not found. "
|
|
384
|
+
"Please provide api_key and secret_key, or set ALPACA_API_KEY and ALPACA_SECRET_KEY environment variables."
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
base_url = os.getenv("ALPACA_BASE_URL", "https://paper-api.alpaca.markets")
|
|
388
|
+
|
|
348
389
|
config = TradingConfig(
|
|
349
390
|
api_key=api_key,
|
|
350
391
|
secret_key=secret_key,
|
|
392
|
+
base_url=base_url,
|
|
351
393
|
paper_trading=paper_trading
|
|
352
394
|
)
|
|
353
|
-
return AlpacaTradingClient(config)
|
|
395
|
+
return AlpacaTradingClient(config)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def get_alpaca_config_from_env() -> Optional[Dict[str, str]]:
|
|
399
|
+
"""
|
|
400
|
+
Get Alpaca configuration from environment variables
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
Dictionary with API configuration or None if not configured
|
|
404
|
+
"""
|
|
405
|
+
api_key = os.getenv("ALPACA_API_KEY")
|
|
406
|
+
secret_key = os.getenv("ALPACA_SECRET_KEY")
|
|
407
|
+
base_url = os.getenv("ALPACA_BASE_URL", "https://paper-api.alpaca.markets")
|
|
408
|
+
|
|
409
|
+
if not api_key or not secret_key:
|
|
410
|
+
return None
|
|
411
|
+
|
|
412
|
+
return {
|
|
413
|
+
"api_key": api_key,
|
|
414
|
+
"secret_key": secret_key,
|
|
415
|
+
"base_url": base_url,
|
|
416
|
+
"is_paper": "paper" in base_url.lower()
|
|
417
|
+
}
|