[Backend] Project Setup - FastAPI Structure and Dependencies #13
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
.kugetsu/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
*.so
|
||||
*.egg
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
.env
|
||||
venv/
|
||||
.venv/
|
||||
*.db
|
||||
data/
|
||||
11
src/backend/.env.example
Normal file
11
src/backend/.env.example
Normal file
@@ -0,0 +1,11 @@
|
||||
DATABASE_URL=sqlite:///./data/app.db
|
||||
SECRET_KEY=your-super-secret-key-change-in-production
|
||||
JWT_ALGORITHM=HS256
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=1440
|
||||
MINIMAX_API_KEY=your-minimax-api-key
|
||||
MINIMAX_MODEL=MiniMax-Text-01
|
||||
AVE_API_KEY=your-ave-cloud-api-key
|
||||
AVE_API_PLAN=free
|
||||
HOST=0.0.0.0
|
||||
PORT=8000
|
||||
DEBUG=false
|
||||
0
src/backend/app/api/__init__.py
Normal file
0
src/backend/app/api/__init__.py
Normal file
52
src/backend/app/api/auth.py
Normal file
52
src/backend/app/api/auth.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||
from sqlalchemy.orm import Session
|
||||
from datetime import timedelta
|
||||
from typing import Annotated
|
||||
|
||||
from ..core.database import get_db
|
||||
from ..core.security import (
|
||||
get_password_hash,
|
||||
verify_password,
|
||||
create_access_token,
|
||||
verify_token,
|
||||
)
|
||||
from ..core.config import get_settings
|
||||
from ..db.schemas import UserCreate, UserResponse, Token
|
||||
|
||||
router = APIRouter()
|
||||
settings = get_settings()
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/token")
|
||||
|
||||
|
||||
@router.post("/register", response_model=UserResponse)
|
||||
def register(user: UserCreate, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.post("/login")
|
||||
def login(
|
||||
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.post("/logout")
|
||||
def logout(token: Annotated[str, Depends(oauth2_scheme)]):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/me", response_model=UserResponse)
|
||||
def get_me(
|
||||
token: Annotated[str, Depends(oauth2_scheme)], db: Session = Depends(get_db)
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
36
src/backend/app/api/backtest.py
Normal file
36
src/backend/app/api/backtest.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
|
||||
from ..core.database import get_db
|
||||
from ..db.schemas import BacktestCreate, BacktestResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/bots/{bot_id}/backtest", response_model=BacktestResponse)
|
||||
def start_backtest(bot_id: str, config: BacktestCreate, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/bots/{bot_id}/backtest/{run_id}", response_model=BacktestResponse)
|
||||
def get_backtest(bot_id: str, run_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/bots/{bot_id}/backtests", response_model=List[BacktestResponse])
|
||||
def list_backtests(bot_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.post("/bots/{bot_id}/backtest/{run_id}/stop")
|
||||
def stop_backtest(bot_id: str, run_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
57
src/backend/app/api/bots.py
Normal file
57
src/backend/app/api/bots.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
|
||||
from ..core.database import get_db
|
||||
from ..db.schemas import BotCreate, BotUpdate, BotResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("", response_model=List[BotResponse])
|
||||
def list_bots(db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.post("", response_model=BotResponse)
|
||||
def create_bot(bot: BotCreate, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{bot_id}", response_model=BotResponse)
|
||||
def get_bot(bot_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.put("/{bot_id}", response_model=BotResponse)
|
||||
def update_bot(bot_id: str, bot: BotUpdate, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{bot_id}")
|
||||
def delete_bot(bot_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.post("/{bot_id}/chat")
|
||||
def chat(bot_id: str, message: dict, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{bot_id}/history")
|
||||
def get_history(bot_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
13
src/backend/app/api/config.py
Normal file
13
src/backend/app/api/config.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/chains")
|
||||
def get_chains():
|
||||
return {"chains": []}
|
||||
|
||||
|
||||
@router.get("/tokens")
|
||||
def get_tokens():
|
||||
return {"tokens": []}
|
||||
38
src/backend/app/api/simulate.py
Normal file
38
src/backend/app/api/simulate.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
|
||||
from ..core.database import get_db
|
||||
from ..db.schemas import SimulationCreate, SimulationResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/bots/{bot_id}/simulate", response_model=SimulationResponse)
|
||||
def start_simulation(
|
||||
bot_id: str, config: SimulationCreate, db: Session = Depends(get_db)
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/bots/{bot_id}/simulate/{run_id}", response_model=SimulationResponse)
|
||||
def get_simulation(bot_id: str, run_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/bots/{bot_id}/simulations", response_model=List[SimulationResponse])
|
||||
def list_simulations(bot_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
|
||||
|
||||
@router.post("/bots/{bot_id}/simulate/{run_id}/stop")
|
||||
def stop_simulation(bot_id: str, run_id: str, db: Session = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Not implemented"
|
||||
)
|
||||
0
src/backend/app/core/__init__.py
Normal file
0
src/backend/app/core/__init__.py
Normal file
25
src/backend/app/core/config.py
Normal file
25
src/backend/app/core/config.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from pydantic_settings import BaseSettings
|
||||
from functools import lru_cache
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
DATABASE_URL: str = "sqlite:///./data/app.db"
|
||||
SECRET_KEY: str
|
||||
JWT_ALGORITHM: str = "HS256"
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 1440
|
||||
MINIMAX_API_KEY: str
|
||||
MINIMAX_MODEL: str = "MiniMax-Text-01"
|
||||
AVE_API_KEY: str
|
||||
AVE_API_PLAN: str = "free"
|
||||
HOST: str = "0.0.0.0"
|
||||
PORT: int = 8000
|
||||
DEBUG: bool = False
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
extra = "allow"
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def get_settings() -> Settings:
|
||||
return Settings()
|
||||
40
src/backend/app/core/database.py
Normal file
40
src/backend/app/core/database.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import os
|
||||
from sqlalchemy import create_engine, event
|
||||
from sqlalchemy.orm import sessionmaker, declarative_base
|
||||
from sqlalchemy.engine import Engine
|
||||
from .config import get_settings
|
||||
|
||||
settings = get_settings()
|
||||
|
||||
if settings.DATABASE_URL.startswith("sqlite"):
|
||||
db_path = settings.DATABASE_URL.replace("sqlite:///", "")
|
||||
os.makedirs(
|
||||
os.path.dirname(db_path) if os.path.dirname(db_path) else ".", exist_ok=True
|
||||
)
|
||||
|
||||
@event.listens_for(Engine, "connect")
|
||||
def set_sqlite_pragma(dbapi_conn, connection_record):
|
||||
cursor = dbapi_conn.cursor()
|
||||
cursor.execute("PRAGMA foreign_keys=ON")
|
||||
cursor.close()
|
||||
|
||||
|
||||
engine = create_engine(
|
||||
settings.DATABASE_URL,
|
||||
connect_args={"check_same_thread": False}
|
||||
if settings.DATABASE_URL.startswith("sqlite")
|
||||
else {},
|
||||
echo=settings.DEBUG,
|
||||
)
|
||||
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
def get_db():
|
||||
db = SessionLocal()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
42
src/backend/app/core/security.py
Normal file
42
src/backend/app/core/security.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Optional
|
||||
from jose import jwt, JWTError
|
||||
from passlib.context import CryptContext
|
||||
from .config import get_settings
|
||||
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
|
||||
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
|
||||
to_encode = data.copy()
|
||||
settings = get_settings()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(
|
||||
minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
|
||||
)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(
|
||||
to_encode, settings.SECRET_KEY, algorithm=settings.JWT_ALGORITHM
|
||||
)
|
||||
return encoded_jwt
|
||||
|
||||
|
||||
def verify_token(token: str) -> Optional[dict[str, Any]]:
|
||||
settings = get_settings()
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
token, settings.SECRET_KEY, algorithms=[settings.JWT_ALGORITHM]
|
||||
)
|
||||
return payload
|
||||
except JWTError:
|
||||
return None
|
||||
|
||||
|
||||
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
||||
return pwd_context.verify(plain_password, hashed_password)
|
||||
|
||||
|
||||
def get_password_hash(password: str) -> str:
|
||||
return pwd_context.hash(password)
|
||||
0
src/backend/app/db/__init__.py
Normal file
0
src/backend/app/db/__init__.py
Normal file
121
src/backend/app/db/models.py
Normal file
121
src/backend/app/db/models.py
Normal file
@@ -0,0 +1,121 @@
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Text,
|
||||
Float,
|
||||
Boolean,
|
||||
DateTime,
|
||||
ForeignKey,
|
||||
Index,
|
||||
JSON,
|
||||
)
|
||||
from sqlalchemy.orm import relationship
|
||||
from ..core.database import Base
|
||||
|
||||
|
||||
def generate_uuid():
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
email = Column(String, unique=True, nullable=False)
|
||||
password_hash = Column(String, nullable=False)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
bots = relationship("Bot", back_populates="user", cascade="all, delete-orphan")
|
||||
|
||||
|
||||
class Bot(Base):
|
||||
__tablename__ = "bots"
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
user_id = Column(String, ForeignKey("users.id"), nullable=False)
|
||||
name = Column(String, nullable=False)
|
||||
description = Column(Text)
|
||||
strategy_config = Column(JSON, nullable=False)
|
||||
llm_config = Column(JSON, nullable=False)
|
||||
status = Column(String, default="draft")
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
user = relationship("User", back_populates="bots")
|
||||
conversations = relationship(
|
||||
"BotConversation", back_populates="bot", cascade="all, delete-orphan"
|
||||
)
|
||||
backtests = relationship(
|
||||
"Backtest", back_populates="bot", cascade="all, delete-orphan"
|
||||
)
|
||||
simulations = relationship(
|
||||
"Simulation", back_populates="bot", cascade="all, delete-orphan"
|
||||
)
|
||||
signals = relationship("Signal", back_populates="bot", cascade="all, delete-orphan")
|
||||
|
||||
|
||||
class BotConversation(Base):
|
||||
__tablename__ = "bot_conversations"
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
bot_id = Column(String, ForeignKey("bots.id"), nullable=False)
|
||||
role = Column(String, nullable=False)
|
||||
content = Column(Text, nullable=False)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
bot = relationship("Bot", back_populates="conversations")
|
||||
|
||||
|
||||
class Backtest(Base):
|
||||
__tablename__ = "backtests"
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
bot_id = Column(String, ForeignKey("bots.id"), nullable=False)
|
||||
started_at = Column(DateTime, nullable=False)
|
||||
ended_at = Column(DateTime)
|
||||
status = Column(String, nullable=False)
|
||||
config = Column(JSON, nullable=False)
|
||||
result = Column(JSON)
|
||||
|
||||
bot = relationship("Bot", back_populates="backtests")
|
||||
|
||||
|
||||
class Simulation(Base):
|
||||
__tablename__ = "simulations"
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
bot_id = Column(String, ForeignKey("bots.id"), nullable=False)
|
||||
started_at = Column(DateTime, nullable=False)
|
||||
status = Column(String, nullable=False)
|
||||
config = Column(JSON, nullable=False)
|
||||
signals = Column(JSON)
|
||||
|
||||
bot = relationship("Bot", back_populates="simulations")
|
||||
|
||||
|
||||
class Signal(Base):
|
||||
__tablename__ = "signals"
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
bot_id = Column(String, ForeignKey("bots.id"), nullable=False)
|
||||
run_id = Column(String, nullable=False)
|
||||
signal_type = Column(String, nullable=False)
|
||||
token = Column(String, nullable=False)
|
||||
price = Column(Float, nullable=False)
|
||||
confidence = Column(Float)
|
||||
reasoning = Column(Text)
|
||||
executed = Column(Boolean, default=False)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
bot = relationship("Bot", back_populates="signals")
|
||||
|
||||
|
||||
Index("idx_bots_user_id", Bot.user_id)
|
||||
Index("idx_conversations_bot_id", BotConversation.bot_id)
|
||||
Index("idx_backtests_bot_id", Backtest.bot_id)
|
||||
Index("idx_simulations_bot_id", Simulation.bot_id)
|
||||
Index("idx_signals_bot_id", Signal.bot_id)
|
||||
Index("idx_signals_run_id", Signal.run_id)
|
||||
93
src/backend/app/db/schemas.py
Normal file
93
src/backend/app/db/schemas.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from pydantic import BaseModel, EmailStr
|
||||
from typing import Optional, List, Any
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class UserCreate(BaseModel):
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
|
||||
class UserResponse(BaseModel):
|
||||
id: str
|
||||
email: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class Token(BaseModel):
|
||||
access_token: str
|
||||
token_type: str
|
||||
|
||||
|
||||
class BotCreate(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
strategy_config: dict
|
||||
llm_config: dict
|
||||
|
||||
|
||||
class BotUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
strategy_config: Optional[dict] = None
|
||||
llm_config: Optional[dict] = None
|
||||
status: Optional[str] = None
|
||||
|
||||
|
||||
class BotResponse(BaseModel):
|
||||
id: str
|
||||
user_id: str
|
||||
name: str
|
||||
description: Optional[str]
|
||||
strategy_config: dict
|
||||
llm_config: dict
|
||||
status: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class BacktestCreate(BaseModel):
|
||||
token: str
|
||||
chain: str
|
||||
timeframe: str
|
||||
start_date: str
|
||||
end_date: str
|
||||
|
||||
|
||||
class BacktestResponse(BaseModel):
|
||||
id: str
|
||||
bot_id: str
|
||||
started_at: datetime
|
||||
ended_at: Optional[datetime]
|
||||
status: str
|
||||
config: dict
|
||||
result: Optional[dict]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class SimulationCreate(BaseModel):
|
||||
token: str
|
||||
chain: str
|
||||
duration_seconds: int = 3600
|
||||
auto_execute: bool = False
|
||||
|
||||
|
||||
class SimulationResponse(BaseModel):
|
||||
id: str
|
||||
bot_id: str
|
||||
started_at: datetime
|
||||
status: str
|
||||
config: dict
|
||||
signals: Optional[List[dict]]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
33
src/backend/app/main.py
Normal file
33
src/backend/app/main.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from .api import auth, bots, backtest, simulate, config
|
||||
|
||||
app = FastAPI(
|
||||
title="Randebu Trading Bot API",
|
||||
description="AI-powered trading bot platform API",
|
||||
version="0.1.0",
|
||||
)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
|
||||
app.include_router(bots.router, prefix="/api/bots", tags=["bots"])
|
||||
app.include_router(backtest.router, prefix="/api", tags=["backtest"])
|
||||
app.include_router(simulate.router, prefix="/api", tags=["simulate"])
|
||||
app.include_router(config.router, prefix="/api/config", tags=["config"])
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def root():
|
||||
return {"status": "ok", "message": "Randebu Trading Bot API"}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health():
|
||||
return {"status": "healthy"}
|
||||
0
src/backend/app/services/__init__.py
Normal file
0
src/backend/app/services/__init__.py
Normal file
4
src/backend/app/services/ai_agent/__init__.py
Normal file
4
src/backend/app/services/ai_agent/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .crew import CrewAgent
|
||||
from .llm_connector import LLMConnector
|
||||
|
||||
__all__ = ["CrewAgent", "LLMConnector"]
|
||||
15
src/backend/app/services/ai_agent/crew.py
Normal file
15
src/backend/app/services/ai_agent/crew.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
class CrewAgent:
|
||||
def __init__(self, role: str, goal: str, backstory: str):
|
||||
self.role = role
|
||||
self.goal = goal
|
||||
self.backstory = backstory
|
||||
|
||||
def execute_task(self, task: str) -> str:
|
||||
raise NotImplementedError("CrewAI agent not yet implemented")
|
||||
|
||||
|
||||
def get_trading_crew():
|
||||
raise NotImplementedError("Trading crew not yet implemented")
|
||||
13
src/backend/app/services/ai_agent/llm_connector.py
Normal file
13
src/backend/app/services/ai_agent/llm_connector.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class LLMConnector:
|
||||
def __init__(self, api_key: str, model: str = "MiniMax-Text-01"):
|
||||
self.api_key = api_key
|
||||
self.model = model
|
||||
|
||||
def chat(self, messages: list[dict], **kwargs):
|
||||
raise NotImplementedError("LLM integration not yet implemented")
|
||||
|
||||
def parse_strategy(self, user_message: str) -> dict:
|
||||
raise NotImplementedError("Strategy parsing not yet implemented")
|
||||
3
src/backend/app/services/backtest/__init__.py
Normal file
3
src/backend/app/services/backtest/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .engine import BacktestEngine
|
||||
|
||||
__all__ = ["BacktestEngine"]
|
||||
15
src/backend/app/services/backtest/engine.py
Normal file
15
src/backend/app/services/backtest/engine.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
class BacktestEngine:
|
||||
def __init__(self, config: Dict[str, Any]):
|
||||
self.config = config
|
||||
|
||||
async def run(self) -> Dict[str, Any]:
|
||||
raise NotImplementedError("Backtest engine not yet implemented")
|
||||
|
||||
async def stop(self):
|
||||
raise NotImplementedError("Backtest stop not yet implemented")
|
||||
|
||||
def get_results(self) -> Dict[str, Any]:
|
||||
raise NotImplementedError("Backtest results not yet implemented")
|
||||
3
src/backend/app/services/simulate/__init__.py
Normal file
3
src/backend/app/services/simulate/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .engine import SimulateEngine
|
||||
|
||||
__all__ = ["SimulateEngine"]
|
||||
15
src/backend/app/services/simulate/engine.py
Normal file
15
src/backend/app/services/simulate/engine.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from typing import Optional, Dict, Any, List
|
||||
|
||||
|
||||
class SimulateEngine:
|
||||
def __init__(self, config: Dict[str, Any]):
|
||||
self.config = config
|
||||
|
||||
async def run(self) -> List[Dict[str, Any]]:
|
||||
raise NotImplementedError("Simulation engine not yet implemented")
|
||||
|
||||
async def stop(self):
|
||||
raise NotImplementedError("Simulation stop not yet implemented")
|
||||
|
||||
def get_signals(self) -> List[Dict[str, Any]]:
|
||||
raise NotImplementedError("Simulation signals not yet implemented")
|
||||
12
src/backend/requirements.txt
Normal file
12
src/backend/requirements.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
fastapi>=0.109.0
|
||||
uvicorn>=0.27.0
|
||||
sqlalchemy>=2.0.0
|
||||
pydantic>=2.5.0
|
||||
pydantic-settings>=2.1.0
|
||||
email-validator>=2.0.0
|
||||
python-jose[cryptography]>=3.3.0
|
||||
passlib[bcrypt]>=1.7.4
|
||||
crewai>=0.1.0
|
||||
anthropic>=0.18.0
|
||||
httpx>=0.26.0
|
||||
python-multipart>=0.0.6
|
||||
11
src/backend/run.py
Normal file
11
src/backend/run.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import uvicorn
|
||||
from app.core.config import get_settings
|
||||
|
||||
if __name__ == "__main__":
|
||||
settings = get_settings()
|
||||
uvicorn.run(
|
||||
"app.main:app",
|
||||
host=settings.HOST,
|
||||
port=settings.PORT,
|
||||
reload=settings.DEBUG,
|
||||
)
|
||||
20
src/backend/setup.py
Normal file
20
src/backend/setup.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="randebu-backend",
|
||||
version="0.1.0",
|
||||
packages=find_packages(),
|
||||
install_requires=[
|
||||
"fastapi>=0.109.0",
|
||||
"uvicorn>=0.27.0",
|
||||
"sqlalchemy>=2.0.0",
|
||||
"pydantic>=2.5.0",
|
||||
"pydantic-settings>=2.1.0",
|
||||
"python-jose[cryptography]>=3.3.0",
|
||||
"passlib[bcrypt]>=1.7.4",
|
||||
"crewai>=0.1.0",
|
||||
"anthropic>=0.18.0",
|
||||
"httpx>=0.26.0",
|
||||
"python-multipart>=0.0.6",
|
||||
],
|
||||
)
|
||||
Reference in New Issue
Block a user