Integrate Redis (10.30.20.70) for locks, cache, and decision state to maximize infra utilization

This commit is contained in:
2026-03-01 10:43:01 -08:00
parent cd8f8430f9
commit 1ca35733cf
5 changed files with 72 additions and 1 deletions

View File

@@ -33,6 +33,8 @@ TRILIUM_TOKEN=REPLACE_ME
N8N_BOT_WEBHOOK=
REDIS_URL=redis://10.30.20.70:6379/0
APP_HOST=0.0.0.0
APP_PORT=8089
DB_PATH=sqlite:///./bot.db

26
bot.py
View File

@@ -18,6 +18,9 @@ from services import (
qdrant_add_memory,
trilium_log,
n8n_emit,
redis_set_json,
redis_get_json,
redis_lock,
)
scheduler = BackgroundScheduler(timezone=settings.timezone)
@@ -42,6 +45,9 @@ def curate_cycle():
def run_cycle():
if not redis_lock('alpaca:run_cycle:lock', ttl=240):
return
db = SessionLocal()
try:
acct = account_snapshot()
@@ -64,7 +70,12 @@ def run_cycle():
if spent >= settings.max_daily_notional:
break
news = searx_news(symbol)
cached_news = redis_get_json(f'alpaca:news:{symbol}')
news = cached_news if cached_news else searx_news(symbol)
if news:
redis_set_json(f'alpaca:news:{symbol}', {'items': news} if isinstance(news, list) else news, ttl=900)
if isinstance(news, dict) and 'items' in news:
news = news['items']
strat = strategy_signals(symbol, news)
memory_hits = qdrant_similar(symbol, json.dumps(news)[:2000], limit=5)
decision = llm_final_decision(symbol, news, strat, memory_hits)
@@ -82,6 +93,19 @@ def run_cycle():
decision["order_usd"] = max(decision.get("order_usd", 0.0), settings.force_paper_min_usd)
decision["reason"] = f"{decision.get('reason','')} | force_paper_trades"
redis_set_json(
f"alpaca:last_decision:{symbol}",
{
"symbol": symbol,
"action": decision["action"],
"confidence": decision["confidence"],
"order_usd": decision["order_usd"],
"reason": decision["reason"],
"ts": datetime.utcnow().isoformat(),
},
ttl=86400,
)
drow = BotDecision(
symbol=symbol,
action=decision["action"],

View File

@@ -40,6 +40,8 @@ class Settings:
n8n_webhook = os.getenv("N8N_BOT_WEBHOOK", "")
redis_url = os.getenv("REDIS_URL", "redis://10.30.20.70:6379/0")
db_path = os.getenv("DB_PATH", "sqlite:///./bot.db")
host = os.getenv("APP_HOST", "0.0.0.0")
port = int(os.getenv("APP_PORT", "8089"))

View File

@@ -6,3 +6,4 @@ apscheduler==3.10.4
python-dotenv==1.0.1
sqlalchemy==2.0.36
pydantic==2.10.3
redis==5.2.1

View File

@@ -3,8 +3,50 @@ import random
import time
import uuid
import requests
import redis
from config import settings
_redis = None
def redis_client():
global _redis
if _redis is None:
try:
_redis = redis.Redis.from_url(settings.redis_url, decode_responses=True, socket_timeout=2)
_redis.ping()
except Exception:
_redis = None
return _redis
def redis_set_json(key: str, value: dict, ttl: int = 3600):
r = redis_client()
if not r:
return False
try:
r.setex(key, ttl, json.dumps(value))
return True
except Exception:
return False
def redis_get_json(key: str):
r = redis_client()
if not r:
return None
try:
v = r.get(key)
return json.loads(v) if v else None
except Exception:
return None
def redis_lock(key: str, ttl: int = 180):
r = redis_client()
if not r:
return True
try:
return bool(r.set(key, str(int(time.time())), ex=ttl, nx=True))
except Exception:
return True
def _ollama_generate(model: str, payload_obj: dict, timeout: int = 45):
payload = {"model": model, "stream": False, "prompt": json.dumps(payload_obj), "format": "json"}