Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
b3ca232
(feat) add controller docs
cardosofede Oct 7, 2025
da80e55
(feat) ignore gateway files
cardosofede Oct 7, 2025
5ca7d25
(feat) add passphrase for gateway in env
cardosofede Oct 7, 2025
15bd8e1
(feat) add gatewya models
cardosofede Oct 7, 2025
13bd8e5
(feat) add gateway service
cardosofede Oct 7, 2025
fad0995
(feat) add deps and include router
cardosofede Oct 7, 2025
8990839
(feat) add gateway func
cardosofede Oct 8, 2025
c74f0e1
(feat) add gateway router
cardosofede Oct 8, 2025
e9e00a7
(feat) add gateway models
cardosofede Oct 8, 2025
5482674
(feat) adapt routers to include gateway
cardosofede Oct 8, 2025
c44d415
(feat) add gateway models and client
cardosofede Oct 8, 2025
5eb9eb1
(feat) remove not necessary endpoint
cardosofede Oct 9, 2025
1955798
(feat) improve models
cardosofede Oct 10, 2025
9907eb8
(feat) improve gateway service
cardosofede Oct 10, 2025
ff5d5f8
(feat) merge network chain
cardosofede Oct 10, 2025
3f00099
(feat) unify on network chain
cardosofede Oct 10, 2025
7b4fe36
(feat) add gateway trading
cardosofede Oct 10, 2025
f316c94
(feat) remove dex trading
cardosofede Oct 13, 2025
b5f63ad
(feat) add gateway trading
cardosofede Oct 13, 2025
00e0237
(feat) add gateway trading models
cardosofede Oct 15, 2025
e5b04d8
(feat) add unique instance ts
cardosofede Oct 15, 2025
57cc733
(feat) adapting models
cardosofede Oct 16, 2025
140c53b
(feat) improve gateway config and trading
cardosofede Oct 16, 2025
c5be1c2
(feat) last gateway improvements
cardosofede Oct 17, 2025
f80ff91
(feat) improve db failures
cardosofede Oct 20, 2025
49f5c84
(feat) update contorllers
cardosofede Oct 20, 2025
b213ae0
(feat) add gateway repositories
cardosofede Oct 21, 2025
ef9ba81
(feat) include in the init
cardosofede Oct 21, 2025
36bfe36
(feat) add db cache in gateway trading
cardosofede Oct 21, 2025
736656f
(feat) add gateway tx poller to accounts service
cardosofede Oct 21, 2025
7676c29
(feat) add restart endpoint
cardosofede Oct 21, 2025
c3528a0
(feat) add gateway tx poller
cardosofede Oct 21, 2025
a43b3e5
(feat) git push
cardosofede Oct 21, 2025
92c5ac5
(feat) improve balance query
cardosofede Oct 23, 2025
19f0be5
(feat) add better error handling
cardosofede Oct 23, 2025
4dc7280
(feat) fix tx polling
cardosofede Oct 23, 2025
78dcd46
(feat) re-order routes
cardosofede Oct 24, 2025
aebe12a
(feat) abstract swap in a different router
cardosofede Oct 27, 2025
4623875
(feat) add clmm router
cardosofede Oct 27, 2025
00ac6c7
(feat) add utils to gateway client
cardosofede Oct 27, 2025
1910be6
(feat) expose clmm and swap routers
cardosofede Oct 27, 2025
f12cafb
(feat) add status parsing
cardosofede Oct 28, 2025
f6a934c
(feat) add position rent
cardosofede Oct 28, 2025
4c1d59a
(feat) improve db models
cardosofede Oct 28, 2025
6b247cf
(feat) add position poll interval
cardosofede Oct 28, 2025
2c04afd
(feat) fix endpoint
cardosofede Oct 28, 2025
d49eb24
(feat) add gateway config settings
cardosofede Oct 28, 2025
e0291a2
(feat) pass gateway config
cardosofede Oct 28, 2025
fc02bc1
(feat) add to the env for local deploy
cardosofede Oct 28, 2025
369997c
(feat) override gateway url when deploying in docker
cardosofede Oct 28, 2025
a85f98d
(feat) improve response snake case
cardosofede Oct 29, 2025
4bd4d04
(feat) add exceprtion
cardosofede Oct 29, 2025
d13c34a
(feat) improve logic for docker deployment
cardosofede Oct 29, 2025
dac5b15
(feat) make host docker internal
cardosofede Oct 29, 2025
7de39e6
(feat) add handling for gateway not able to execute
cardosofede Oct 29, 2025
9dbcdf7
(feat) max limits bins optional
cardosofede Oct 29, 2025
f249adb
(feat) add info of general clmm pools
cardosofede Oct 29, 2025
6d9eb65
(feat) add query func
cardosofede Oct 29, 2025
73f0b68
(feat) remove import
cardosofede Oct 29, 2025
2f96762
(feat) exclude add and remove liquidity features
cardosofede Oct 29, 2025
5f1827f
(feat) move pct to positions
cardosofede Oct 29, 2025
31bac96
(feat) calculate percentage
cardosofede Oct 29, 2025
6a0b9dc
(feat) add management of failing position
cardosofede Oct 31, 2025
c2919d0
(feat) improve pools reponse
cardosofede Oct 31, 2025
019100d
(feat) add fee collection when closing positions
cardosofede Oct 31, 2025
ff69886
(feat) reduce poll interval
cardosofede Oct 31, 2025
9d3e48f
(feat) add support for linux
cardosofede Oct 31, 2025
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,6 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Hummingbot Gateway files
gateway-files/
83 changes: 83 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Stores all trading data including:
- Positions and funding payments
- Performance metrics

**Note:** The database is automatically initialized using environment variables (`POSTGRES_USER`, `POSTGRES_DB`, `POSTGRES_PASSWORD`). The included `init-db.sql` script serves as a safety net for edge cases where automatic initialization doesn't complete properly.

### 2. EMQX Message Broker
Enables real-time communication with trading bots:
- Receives live updates from running bots
Expand Down Expand Up @@ -261,11 +263,92 @@ All API endpoints require HTTP Basic Authentication. Include your configured cre
curl -u username:password http://localhost:8000/endpoint
```

## Troubleshooting

### Database Connection Issues

If you encounter PostgreSQL database connection errors (such as "role 'hbot' does not exist" or "database 'hummingbot_api' does not exist"), use the automated fix script:

```bash
chmod +x fix-database.sh
./fix-database.sh
```

This script will:
1. Check if PostgreSQL is running
2. Verify that the `hbot` user and `hummingbot_api` database exist
3. Automatically fix any missing configuration
4. Test the connection to ensure everything works

#### Manual Database Verification

If you prefer to check manually:

```bash
# Check if containers are running
docker ps | grep -E "hummingbot-postgres|hummingbot-broker"

# Check PostgreSQL logs
docker logs hummingbot-postgres

# Verify database connection
docker exec -it hummingbot-postgres psql -U hbot -d hummingbot_api

# If connection fails, run the initialization script
docker exec -i hummingbot-postgres psql -U postgres < init-db.sql
```

#### Complete Database Reset

If you need to start fresh (⚠️ this will delete all data):

```bash
# Stop all containers and remove volumes
docker compose down -v

# Restart setup
./setup.sh
```

### EMQX Broker Issues

If bots can't connect to the broker:

```bash
# Check EMQX status
docker logs hummingbot-broker

# Restart EMQX
docker compose restart emqx

# Access EMQX dashboard (if needed)
# http://localhost:18083
# Default credentials: admin/public
```

### Common Issues

**Issue**: API won't start - "Database connection failed"
- **Solution**: Run `./fix-database.sh` to repair the database configuration

**Issue**: Bot containers won't start
- **Solution**: Check Docker daemon is running and you have sufficient resources

**Issue**: Can't access API at localhost:8000
- **Solution**: Verify the API container is running: `docker ps | grep hummingbot-api`

**Issue**: Authentication fails
- **Solution**: Check your USERNAME and PASSWORD in the `.env` file

**Issue**: Old bot data causing conflicts
- **Solution**: Clean up old volumes: `docker compose down -v` (⚠️ deletes data)

## Support & Documentation

- **API Documentation**: Available at `http://localhost:8000/docs` when running
- **Detailed Examples**: Check the `CLAUDE.md` file for comprehensive API usage examples
- **Issues**: Report bugs and feature requests through the project's issue tracker
- **Database Troubleshooting**: Use `./fix-database.sh` for automated fixes
---

Ready to start trading? Deploy your first account and start exploring the powerful capabilities of the Hummingbot API!
160 changes: 160 additions & 0 deletions bots/controllers/directional_trading/bollingrid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
from decimal import Decimal
from typing import List

import pandas_ta as ta # noqa: F401
from pydantic import Field, field_validator
from pydantic_core.core_schema import ValidationInfo

from hummingbot.core.data_type.common import TradeType
from hummingbot.data_feed.candles_feed.data_types import CandlesConfig
from hummingbot.strategy_v2.controllers.directional_trading_controller_base import (
DirectionalTradingControllerBase,
DirectionalTradingControllerConfigBase,
)
from hummingbot.strategy_v2.executors.grid_executor.data_types import GridExecutorConfig


class BollinGridControllerConfig(DirectionalTradingControllerConfigBase):
controller_name: str = "bollingrid"
candles_config: List[CandlesConfig] = []
candles_connector: str = Field(
default=None,
json_schema_extra={
"prompt": "Enter the connector for the candles data, leave empty to use the same exchange as the connector: ",
"prompt_on_new": True})
candles_trading_pair: str = Field(
default=None,
json_schema_extra={
"prompt": "Enter the trading pair for the candles data, leave empty to use the same trading pair as the connector: ",
"prompt_on_new": True})
interval: str = Field(
default="3m",
json_schema_extra={
"prompt": "Enter the candle interval (e.g., 1m, 5m, 1h, 1d): ",
"prompt_on_new": True})
bb_length: int = Field(
default=100,
json_schema_extra={"prompt": "Enter the Bollinger Bands length: ", "prompt_on_new": True})
bb_std: float = Field(default=2.0)
bb_long_threshold: float = Field(default=0.0)
bb_short_threshold: float = Field(default=1.0)

# Grid-specific parameters
grid_start_price_coefficient: float = Field(
default=0.25,
json_schema_extra={"prompt": "Grid start price coefficient (multiplier of BB width): ", "prompt_on_new": True})
grid_end_price_coefficient: float = Field(
default=0.75,
json_schema_extra={"prompt": "Grid end price coefficient (multiplier of BB width): ", "prompt_on_new": True})
grid_limit_price_coefficient: float = Field(
default=0.35,
json_schema_extra={"prompt": "Grid limit price coefficient (multiplier of BB width): ", "prompt_on_new": True})
min_spread_between_orders: Decimal = Field(
default=Decimal("0.005"),
json_schema_extra={"prompt": "Minimum spread between grid orders (e.g., 0.005 for 0.5%): ", "prompt_on_new": True})
order_frequency: int = Field(
default=2,
json_schema_extra={"prompt": "Order frequency (seconds between grid orders): ", "prompt_on_new": True})
max_orders_per_batch: int = Field(
default=1,
json_schema_extra={"prompt": "Maximum orders per batch: ", "prompt_on_new": True})
min_order_amount_quote: Decimal = Field(
default=Decimal("6"),
json_schema_extra={"prompt": "Minimum order amount in quote currency: ", "prompt_on_new": True})
max_open_orders: int = Field(
default=5,
json_schema_extra={"prompt": "Maximum number of open orders: ", "prompt_on_new": True})

@field_validator("candles_connector", mode="before")
@classmethod
def set_candles_connector(cls, v, validation_info: ValidationInfo):
if v is None or v == "":
return validation_info.data.get("connector_name")
return v

@field_validator("candles_trading_pair", mode="before")
@classmethod
def set_candles_trading_pair(cls, v, validation_info: ValidationInfo):
if v is None or v == "":
return validation_info.data.get("trading_pair")
return v


class BollinGridController(DirectionalTradingControllerBase):
def __init__(self, config: BollinGridControllerConfig, *args, **kwargs):
self.config = config
self.max_records = self.config.bb_length
if len(self.config.candles_config) == 0:
self.config.candles_config = [CandlesConfig(
connector=config.candles_connector,
trading_pair=config.candles_trading_pair,
interval=config.interval,
max_records=self.max_records
)]
super().__init__(config, *args, **kwargs)

async def update_processed_data(self):
df = self.market_data_provider.get_candles_df(connector_name=self.config.candles_connector,
trading_pair=self.config.candles_trading_pair,
interval=self.config.interval,
max_records=self.max_records)
# Add indicators
df.ta.bbands(length=self.config.bb_length, std=self.config.bb_std, append=True)
bbp = df[f"BBP_{self.config.bb_length}_{self.config.bb_std}"]
bb_width = df[f"BBB_{self.config.bb_length}_{self.config.bb_std}"]

# Generate signal
long_condition = bbp < self.config.bb_long_threshold
short_condition = bbp > self.config.bb_short_threshold

# Generate signal
df["signal"] = 0
df.loc[long_condition, "signal"] = 1
df.loc[short_condition, "signal"] = -1
signal = df["signal"].iloc[-1]
close = df["close"].iloc[-1]
current_bb_width = bb_width.iloc[-1] / 100
if signal == -1:
end_price = close * (1 + current_bb_width * self.config.grid_start_price_coefficient)
start_price = close * (1 - current_bb_width * self.config.grid_end_price_coefficient)
limit_price = close * (1 + current_bb_width * self.config.grid_limit_price_coefficient)
elif signal == 1:
start_price = close * (1 - current_bb_width * self.config.grid_start_price_coefficient)
end_price = close * (1 + current_bb_width * self.config.grid_end_price_coefficient)
limit_price = close * (1 - current_bb_width * self.config.grid_limit_price_coefficient)
else:
start_price = None
end_price = None
limit_price = None

# Update processed data
self.processed_data["signal"] = df["signal"].iloc[-1]
self.processed_data["features"] = df
self.processed_data["grid_params"] = {
"start_price": start_price,
"end_price": end_price,
"limit_price": limit_price
}

def get_executor_config(self, trade_type: TradeType, price: Decimal, amount: Decimal):
"""
Get the grid executor config based on the trade_type, price and amount.
Uses configurable grid parameters from the controller config.
"""
return GridExecutorConfig(
timestamp=self.market_data_provider.time(),
connector_name=self.config.connector_name,
trading_pair=self.config.trading_pair,
start_price=self.processed_data["grid_params"]["start_price"],
end_price=self.processed_data["grid_params"]["end_price"],
limit_price=self.processed_data["grid_params"]["limit_price"],
side=trade_type,
triple_barrier_config=self.config.triple_barrier_config,
leverage=self.config.leverage,
min_spread_between_orders=self.config.min_spread_between_orders,
total_amount_quote=amount * price,
order_frequency=self.config.order_frequency,
max_orders_per_batch=self.config.max_orders_per_batch,
min_order_amount_quote=self.config.min_order_amount_quote,
max_open_orders=self.config.max_open_orders,
)
Loading