Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/performance page endpoints #36

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
03b481d
(feat) add database endpoints
tomasgaudino Sep 21, 2024
14068e7
(feat) add checkpoint management endpoints + add controllers table to…
tomasgaudino Sep 21, 2024
ceb0f5b
(feat) load controllers
tomasgaudino Sep 21, 2024
5fdbaba
(feat) add performance endpoints
tomasgaudino Sep 21, 2024
503c86e
(feat) improve etl performance + remove controller type from performa…
tomasgaudino Sep 30, 2024
c121170
(feat) replace unpacking method by dict definition for executor info …
tomasgaudino Oct 12, 2024
8e15d7b
Update Makefile
david-hummingbot Jul 22, 2024
1ab63e7
fix-conda-env
david-hummingbot Oct 14, 2024
90b7366
update python-multipart version
david-hummingbot Oct 25, 2024
b286bc1
(feat) add logfire dependency
cardosofede Oct 13, 2024
2d9a462
(feat) add logfire config
cardosofede Oct 13, 2024
2d7b6d0
(feat) add connector name to the logs
cardosofede Oct 13, 2024
790d300
(feat) add user and pass for the api
cardosofede Oct 29, 2024
f1341c5
(feat) add grid strike
cardosofede Oct 29, 2024
e98e77c
(feat) update environment
cardosofede Oct 29, 2024
197dac7
(feat) add security
cardosofede Oct 29, 2024
353ee91
(fix) typo
cardosofede Oct 31, 2024
6364add
(feat) add database endpoints
tomasgaudino Sep 21, 2024
f232b1a
(feat) add performance endpoints
tomasgaudino Sep 21, 2024
86f405d
(fix) fix main
tomasgaudino Nov 13, 2024
08760f3
Merge branch 'main' into feat/performance-page-endpoints
tomasgaudino Nov 13, 2024
9bf3bd7
(fix) remove * from .gitignore
tomasgaudino Nov 13, 2024
2dbaa17
(feat) add lost lines from bad github management
tomasgaudino Nov 15, 2024
23c0286
(feat) add debug mode
tomasgaudino Nov 15, 2024
394d6ec
(feat) update compose file
tomasgaudino Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ version: "3.9"

services:
backend-api:
build: .
container_name: backend-api
image: hummingbot/backend-api:latest
ports:
- "8000:8000"
volumes:
- ./bots:/backend-api/bots
- /var/run/docker.sock:/var/run/docker.sock
env_file:
- .env
environment:
- BROKER_HOST=emqx
- BROKER_PORT=1883
- USERNAME=admin
- PASSWORD=admin
networks:
- emqx-bridge
emqx:
Expand Down
9 changes: 6 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials

from routers import manage_accounts, manage_backtesting, manage_broker_messages, manage_docker, manage_files, manage_market_data
from routers import manage_accounts, manage_backtesting, manage_broker_messages, manage_docker, manage_files, \
manage_market_data, manage_databases, manage_performance

load_dotenv()
security = HTTPBasic()

username = os.getenv("USERNAME", "admin")
password = os.getenv("PASSWORD", "admin")
debug_mode = os.getenv("DEBUG_MODE", False)

app = FastAPI()

Expand All @@ -30,7 +32,7 @@ def auth_user(
is_correct_password = secrets.compare_digest(
current_password_bytes, correct_password_bytes
)
if not (is_correct_username and is_correct_password):
if not (is_correct_username and is_correct_password) and not debug_mode:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
Expand All @@ -43,4 +45,5 @@ def auth_user(
app.include_router(manage_files.router, dependencies=[Depends(auth_user)])
app.include_router(manage_market_data.router, dependencies=[Depends(auth_user)])
app.include_router(manage_backtesting.router, dependencies=[Depends(auth_user)])
app.include_router(manage_accounts.router, dependencies=[Depends(auth_user)])
app.include_router(manage_databases.router, dependencies=[Depends(auth_user)])
app.include_router(manage_performance.router, dependencies=[Depends(auth_user)])
100 changes: 100 additions & 0 deletions routers/manage_databases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import json
import time

from typing import List, Dict, Any

import pandas as pd

from utils.etl_databases import HummingbotDatabase, ETLPerformance
from fastapi import APIRouter

from utils.file_system import FileSystemUtil

router = APIRouter(tags=["Database Management"])
file_system = FileSystemUtil()


@router.post("/list-databases", response_model=List[str])
async def list_databases():
return file_system.list_databases()


@router.post("/read-databases", response_model=List[Dict[str, Any]])
async def read_databases(db_paths: List[str] = None):
dbs = []
for db_path in db_paths:
db = HummingbotDatabase(db_path)
try:
db_content = {
"db_name": db.db_name,
"db_path": db.db_path,
"healthy": db.status["general_status"],
"status": db.status,
"tables": {
"orders": json.dumps(db.get_orders().to_dict()),
"trade_fill": json.dumps(db.get_trade_fills().to_dict()),
"executors": json.dumps(db.get_executors_data().to_dict()),
"order_status": json.dumps(db.get_order_status().to_dict()),
"controllers": json.dumps(db.get_controllers_data().to_dict())
}
}
except Exception as e:
print(f"Error reading database {db_path}: {str(e)}")
db_content = {
"db_name": "",
"db_path": db_path,
"healthy": False,
"status": db.status,
"tables": {}
}
dbs.append(db_content)
return dbs


@router.post("/create-checkpoint", response_model=Dict[str, Any])
async def create_checkpoint(db_paths: List[str]):
try:
dbs = await read_databases(db_paths)

healthy_dbs = [db for db in dbs if db["healthy"]]

table_names = ["trade_fill", "orders", "order_status", "executors", "controllers"]
tables_dict = {name: pd.DataFrame() for name in table_names}

for db in healthy_dbs:
for table_name in table_names:
new_data = pd.DataFrame(json.loads(db["tables"][table_name]))
new_data["db_path"] = db["db_path"]
new_data["db_name"] = db["db_name"]
tables_dict[table_name] = pd.concat([tables_dict[table_name], new_data])

etl = ETLPerformance(db_path=f"bots/data/checkpoint_{str(int(time.time()))}.sqlite")
etl.create_tables()
etl.insert_data(tables_dict)
return {"message": "Checkpoint created successfully."}
except Exception as e:
return {"message": f"Error: {str(e)}"}


@router.post("/list-checkpoints", response_model=List[str])
async def list_checkpoints(full_path: bool):
return file_system.list_checkpoints(full_path)


@router.post("/load-checkpoint")
async def load_checkpoint(checkpoint_path: str):
try:
etl = ETLPerformance(checkpoint_path)
executor = etl.load_executors()
order = etl.load_orders()
trade_fill = etl.load_trade_fill()
controllers = etl.load_controllers()
checkpoint_data = {
"executors": json.dumps(executor.to_dict()),
"orders": json.dumps(order.to_dict()),
"trade_fill": json.dumps(trade_fill.to_dict()),
"controllers": json.dumps(controllers.to_dict())
}
return checkpoint_data
except Exception as e:
return {"message": f"Error: {str(e)}"}
28 changes: 28 additions & 0 deletions routers/manage_performance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from fastapi import APIRouter
from typing import Any, Dict

from hummingbot.strategy_v2.backtesting.backtesting_engine_base import BacktestingEngineBase

from utils.etl_databases import PerformanceDataSource

router = APIRouter(tags=["Market Performance"])


@router.post("/get-performance-results")
async def get_performance_results(payload: Dict[str, Any]):
executors = payload.get("executors")
data_source = PerformanceDataSource(executors)
performance_results = {}
try:
backtesting_engine = BacktestingEngineBase()
executor_info_list = data_source.executor_info_list
performance_results["results"] = backtesting_engine.summarize_results(executor_info_list )
results = performance_results["results"]
results["sharpe_ratio"] = results["sharpe_ratio"] if results["sharpe_ratio"] is not None else 0
return {
"executors": executors,
"results": performance_results["results"],
}

except Exception as e:
return {"error": str(e)}
Loading
Loading