Back to Home

How to Build a Crypto Trading Bot with CoinGlass API
Building a crypto trading bot is not just about writing a script that buys when price goes up and sells when price goes down. That kind of bot may work for a simple demo, but it is usually not enough for real crypto markets, especially if the bot trades futures, perpetual contracts, or leveraged...
B
Blizine Admin
·26 min read·0 views
Building a crypto trading bot is not just about writing a script that buys when price goes up and sells when price goes down.
That kind of bot may work for a simple demo, but it is usually not enough for real crypto markets, especially if the bot trades futures, perpetual contracts, or leveraged positions.
Crypto markets are heavily influenced by derivatives. A large price move may be caused by spot buying, but it may also be caused by:
Open interest expansion
Funding rate imbalance
Short liquidations
Long liquidations
Leverage build-up
Forced deleveraging
Order book liquidity gaps
Aggressive taker buy or sell pressure
Cross-exchange positioning
This is why a serious crypto trading bot needs more than price data. It needs market structure data.
CoinGlass API is useful in this context because it provides access to key crypto derivatives data such as open interest, funding rates, liquidations, long/short ratios, order book data, options data, ETF flow data, and other market indicators. CoinGlass API V4 is the current recommended version, while V1–V3 are deprecated and mainly kept for backward compatibility. ([coinglass][1])
In this guide, we will walk through how to build a crypto trading bot using CoinGlass API as a market intelligence layer. The goal is not to build a perfect money-printing machine. The goal is to design a more market-aware trading bot that can understand when a signal is strong, when risk is elevated, and when it is better to stay out.
1. What Kind of Trading Bot Are We Building?
Before writing code, we need to define the bot.
A crypto trading bot can mean many different things:
Bot Type
Description
Data Needed
Price alert bot
Sends alerts when price reaches a level
Price data
Trend-following bot
Buys breakouts and sells breakdowns
Price, volume, OI
Grid bot
Places buy and sell orders in a range
Price, volatility, risk filters
Funding rate bot
Monitors funding rate opportunities
Funding rate, OI, exchange data
Liquidation alert bot
Detects abnormal liquidation events
Liquidation data
Risk management bot
Reduces exposure during extreme market stress
OI, funding, liquidations
Quant strategy bot
Uses multiple factors to generate signals
Historical and real-time data
In this article, we will build a derivatives-aware trading bot framework.
The bot will:
Fetch market data from CoinGlass API
Read open interest, funding rate, and liquidation data
Convert raw data into trading features
Generate market state signals
Combine derivatives signals with a simple price signal
Output a trading decision
Adjust position size based on market risk
This is a realistic architecture because CoinGlass API is best used as a market intelligence layer, while exchange APIs are usually used as the execution layer.
2. CoinGlass API vs Exchange API
Many developers ask:
Why not just use Binance API, OKX API, Bybit API, or another exchange API?
The answer is simple: exchange APIs and CoinGlass API solve different problems.
Function
Exchange API
CoinGlass API
Place orders
Yes
No
Manage account balance
Yes
No
Read current position
Yes
No
Get exchange-specific price
Yes
Sometimes, depending on endpoint
Compare multiple exchanges
Manual work needed
More suitable
Get aggregated derivatives data
Harder
Designed for this
Get funding rate context
Limited to exchange
Broader derivatives view
Get liquidation data
Exchange-specific or limited
More useful as an aggregated market signal
Build market structure signals
Requires heavy engineering
More direct
Execute trades
Yes
No
A good trading system usually uses both:
Exchange API = execution layer
CoinGlass API = market intelligence layer
The exchange API answers:
Can I place this order?
What is my account balance?
What is my current position?
CoinGlass API helps answer:
Should I place this order?
Is the market crowded?
Is leverage building up?
Are traders being liquidated?
Is this breakout healthy?
That distinction is important. A trading bot should not only know how to trade. It should also know when not to trade.
3. Why CoinGlass API Is Useful for Trading Bots
CoinGlass provides a broad set of crypto market data. According to CoinGlass public API materials, its crypto API covers derivatives, spot, options, ETF markets, order book data, and market snapshot data such as price, volume, open interest, and funding rates. ([coinglass][2])
For trading bots, the most useful data categories are:
Data Type
Why It Matters
Open Interest
Shows whether leveraged capital is entering or leaving
Funding Rate
Measures long/short cost and crowding
Liquidations
Shows forced position closures
Long/Short Ratio
Helps detect positioning imbalance
Taker Buy/Sell Volume
Shows aggressive buying or selling pressure
Order Book Data
Helps analyze liquidity and execution risk
Liquidation Heatmap
Helps identify potential liquidation zones
ETF Flow Data
Useful for broader market flow analysis
Options Data
Useful for volatility and institutional positioning
CoinGlass API official materials list futures modules such as open interest, funding rate, liquidation data, global long/short ratios, top trader long/short ratios, and taker buy/sell volume. Some example endpoint categories include /api/futures/openInterest/ohlc-history, /api/futures/fundingRate/oi-weight-ohlc-history, and /api/futures/liquidation/aggregated-history. ([coinglass][3])
These data points help the bot understand market state instead of only reacting to price.
4. Trading Bot Architecture
A simple crypto trading bot architecture looks like this:
Data Layer
↓
Feature Layer
↓
Signal Layer
↓
Risk Layer
↓
Execution Layer
↓
Logging / Monitoring Layer
Let’s define each layer.
Layer
Purpose
Data Layer
Fetch raw market data from APIs
Feature Layer
Convert raw data into useful indicators
Signal Layer
Generate buy, sell, or hold signals
Risk Layer
Adjust position size and filter bad trades
Execution Layer
Place orders through exchange API
Logging Layer
Store decisions, errors, and performance data
CoinGlass API sits mainly in the Data Layer, but its output is used heavily in the Feature, Signal, and Risk layers.
A practical bot architecture may look like this:
CoinGlass API
- Open Interest
- Funding Rate
- Liquidation Data
- Long/Short Ratio
- Order Flow
Exchange API
- Price Candles
- Account Balance
- Order Placement
- Position Management
Trading Bot
- Feature Engineering
- Signal Generation
- Risk Filtering
- Position Sizing
- Execution
This article will focus on the CoinGlass API side and the strategy framework. You can connect the final decision output to your preferred exchange API.
5. Core Strategy Idea
A common beginner bot does this:
If price breaks above moving average → BUY
If price breaks below moving average → SELL
This is simple, but it ignores derivatives market structure.
A better bot does this:
If price gives BUY signal
AND funding rate is not extremely high
AND open interest supports the move
AND liquidation risk is not extreme
THEN allow the trade
Otherwise, reduce size or skip the trade
This is more realistic.
The bot does not simply ask:
Did price go up?
It asks:
Is this price move healthy?
Is leverage supporting it?
Is one side too crowded?
Is the market entering a liquidation cascade?
That is the main difference between a basic bot and a market-aware bot.
6. Key CoinGlass Data for the Bot
For this trading bot, we will focus on three core data types:
Open Interest
Funding Rate
Liquidation Data
These three are enough to build a strong first version.
6.1 Open Interest
Open Interest, or OI, measures the total open futures or perpetual contract positions.
It helps answer:
Is new leverage entering the market?
Price
Open Interest
Possible Interpretation
Price up
OI up
New positions support the move
Price up
OI down
Shorts may be closing
Price down
OI up
New shorts may be entering
Price down
OI down
Longs may be closing or liquidated
Price flat
OI up
Leverage is building before a possible breakout
For bots, OI is useful because it helps confirm whether a price movement is supported by new market participation.
Example:
BTC price rises 3%.
Open interest also rises.
Funding rate remains neutral.
This may be a healthier bullish trend.
But:
BTC price rises 3%.
Open interest rises sharply.
Funding rate becomes extremely positive.
Long/short ratio becomes heavily long.
This may be a crowded long environment.
6.2 Funding Rate
Funding rate is the periodic payment between longs and shorts in perpetual futures.
Funding Rate
Meaning
Positive
Longs pay shorts
Negative
Shorts pay longs
Extremely positive
Longs may be crowded
Extremely negative
Shorts may be crowded
Neutral
Market is more balanced
Funding rate is not a direct buy or sell signal.
A common mistake is:
Funding high = short
Funding low = long
That is too simple.
A better interpretation is:
Funding high = long side may be crowded
Funding low = short side may be crowded
Funding rate is best used as a filter.
Examples:
Price Signal
Funding Rate
Bot Action
BUY
Neutral
Allow trade
BUY
Extremely positive
Reduce size or skip
SELL
Neutral
Allow trade
SELL
Extremely negative
Reduce size or skip
BUY
Negative + short liquidations rising
Possible short squeeze setup
6.3 Liquidation Data
Liquidation data shows forced position closures.
It helps answer:
Which side is being forced out?
Liquidation Event
Interpretation
Long liquidation spike
Longs are being forced out
Short liquidation spike
Shorts are being squeezed
Both sides liquidated
Extreme volatility
Liquidations decline
Leverage pressure may be cooling
Liquidation spike + price recovery
Possible false breakdown or liquidity sweep
Liquidation data is extremely useful for risk management.
A bot can use it to:
Avoid trading during liquidation cascades
Detect short squeeze conditions
Detect long squeeze conditions
Reduce position size during market stress
Avoid buying or selling after a move is already exhausted
7. API Setup
CoinGlass API V4 uses the following base URL in public documentation and examples:
https://open-api-v4.coinglass.com
Requests generally use the CG-API-KEY header for authentication. CoinGlass documentation states that API V4 brings improved performance, faster response times, and optimized data retrieval. ([coinglass][4])
First, install the required Python packages:
pip install requests pandas python-dotenv
Create a .env file:
COINGLASS_API_KEY=your_api_key_here
Then create a Python file named:
bot.py
Basic API client:
import os
import requests
import pandas as pd
from dotenv import load_dotenv
load_dotenv()
BASE_URL = "https://open-api-v4.coinglass.com"
API_KEY = os.getenv("COINGLASS_API_KEY")
if not API_KEY:
raise RuntimeError("Missing COINGLASS_API_KEY environment variable")
HEADERS = {
"CG-API-KEY": API_KEY,
"Accept": "application/json"
}
def request_coinglass(endpoint, params=None):
"""
Send a GET request to CoinGlass API.
"""
url = f"{BASE_URL}{endpoint}"
response = requests.get(
url,
headers=HEADERS,
params=params,
timeout=10
)
response.raise_for_status()
return response.json()
This function will be reused for all CoinGlass API requests.
8. Add Safe Request Handling
Production bots should not crash because one API request fails.
Let’s improve the request function with retries:
import time
def safe_request_coinglass(endpoint, params=None, retries=3, sleep_seconds=2):
"""
Send a GET request with retry logic.
"""
last_error = None
for attempt in range(retries):
try:
return request_coinglass(endpoint, params)
except requests.RequestException as error:
last_error = error
print(f"Request failed: attempt {attempt + 1}/{retries}: {error}")
time.sleep(sleep_seconds)
raise last_error
This is important because live bots must handle:
Network errors
Timeout errors
Temporary API issues
Rate limits
Invalid responses
Missing data
A trading bot should fail safely, not blindly continue with broken data.
9. Fetch Open Interest Data
CoinGlass public API materials list Open Interest endpoints such as:
/api/futures/openInterest/ohlc-history
/api/futures/openInterest/aggregated-history
/api/futures/openInterest/exchange-list
For this example, we will use an OHLC-style history endpoint. Always verify endpoint names and parameters with the latest official documentation before production use.
def fetch_open_interest(symbol="BTC", interval="1h", limit=100):
endpoint = "/api/futures/openInterest/ohlc-history"
params = {
"symbol": symbol,
"interval": interval,
"limit": limit
}
return safe_request_coinglass(endpoint, params)
Convert the response into a DataFrame:
def to_dataframe(raw):
"""
Convert a CoinGlass API response to a pandas DataFrame.
Adjust this function based on the actual response shape.
"""
data = raw.get("data", [])
if isinstance(data, dict):
# Some APIs may return nested structures.
# Adjust based on actual response.
rows = data.get("list", [])
else:
rows = data
df = pd.DataFrame(rows)
if df.empty:
return df
if "time" in df.columns:
df["time"] = pd.to_datetime(df["time"], unit="ms", errors="coerce")
return df
Add OI features:
def add_open_interest_features(df):
data = df.copy()
# Adjust field names based on actual API response.
if "close" in data.columns:
data["oi_close"] = pd.to_numeric(data["close"], errors="coerce")
elif "openInterest" in data.columns:
data["oi_close"] = pd.to_numeric(data["openInterest"], errors="coerce")
else:
raise ValueError("No recognizable open interest field found")
data["oi_change"] = data["oi_close"].pct_change()
data["oi_change_24"] = data["oi_close"].pct_change(24)
return data
10. Fetch Funding Rate Data
CoinGlass public materials list funding rate endpoints such as:
/api/futures/fundingRate/ohlc-history
/api/futures/fundingRate/oi-weight-ohlc-history
/api/futures/fundingRate/exchange-list
A bot can use funding rate to detect crowded long or short conditions.
def fetch_funding_rate(symbol="BTC", interval="1h", limit=100):
endpoint = "/api/futures/fundingRate/oi-weight-ohlc-history"
params = {
"symbol": symbol,
"interval": interval,
"limit": limit
}
return safe_request_coinglass(endpoint, params)
Add funding rate features:
def zscore(series, window=24):
mean = series.rolling(window).mean()
std = series.rolling(window).std()
return (series - mean) / std
def add_funding_features(df, window=24):
data = df.copy()
# Adjust field name based on actual API response.
if "close" in data.columns:
data["funding_close"] = pd.to_numeric(data["close"], errors="coerce")
elif "fundingRate" in data.columns:
data["funding_close"] = pd.to_numeric(data["fundingRate"], errors="coerce")
else:
raise ValueError("No recognizable funding rate field found")
data["funding_z"] = zscore(data["funding_close"], window)
return data
Interpretation:
Funding Z-score
Meaning
Above 2
Extremely positive funding
1 to 2
Moderately positive funding
-1 to 1
Neutral
-2 to -1
Moderately negative funding
Below -2
Extremely negative funding
This lets the bot detect whether the market is unusually long-heavy or short-heavy.
11. Fetch Liquidation Data
CoinGlass public materials list liquidation endpoints such as:
/api/futures/liquidation/history
/api/futures/liquidation/aggregated-history
/api/futures/liquidation/heatmap/model2
For this example:
def fetch_liquidation_history(
symbol="BTC",
exchanges="Binance,OKX,Bybit",
interval="1h",
limit=100
):
endpoint = "/api/futures/liquidation/aggregated-history"
params = {
"exchange_list": exchanges,
"symbol": symbol,
"interval": interval,
"limit": limit
}
return safe_request_coinglass(endpoint, params)
Add liquidation features:
def add_liquidation_features(df, window=24):
data = df.copy()
rename_map = {
"longLiquidation": "long_liquidation",
"shortLiquidation": "short_liquidation",
"long_liq": "long_liquidation",
"short_liq": "short_liquidation"
}
data = data.rename(columns=rename_map)
if "long_liquidation" not in data.columns:
raise ValueError("No long liquidation field found")
if "short_liquidation" not in data.columns:
raise ValueError("No short liquidation field found")
data["long_liquidation"] = pd.to_numeric(
data["long_liquidation"],
errors="coerce"
)
data["short_liquidation"] = pd.to_numeric(
data["short_liquidation"],
errors="coerce"
)
data["long_liq_z"] = zscore(data["long_liquidation"], window)
data["short_liq_z"] = zscore(data["short_liquidation"], window)
data["total_liquidation"] = (
data["long_liquidation"] + data["short_liquidation"]
)
data["total_liq_z"] = zscore(data["total_liquidation"], window)
return data
Interpretation:
Liquidation Signal
Meaning
Long liquidation z-score > 2
Longs are being liquidated unusually
Short liquidation z-score > 2
Shorts are being liquidated unusually
Total liquidation z-score > 3
Extreme risk environment
Liquidation z-score near 0
Normal environment
12. Merge Data into One Market Table
Now we need to merge open interest, funding rate, and liquidation data by timestamp.
def prepare_time_column(df):
data = df.copy()
if "time" not in data.columns:
raise ValueError("Missing time column")
data = data.dropna(subset=["time"])
data = data.sort_values("time")
return data
def merge_market_data(oi_df, funding_df, liquidation_df):
oi = prepare_time_column(oi_df)
funding = prepare_time_column(funding_df)
liquidation = prepare_time_column(liquidation_df)
merged = pd.merge_asof(
oi,
funding,
on="time",
direction="nearest",
tolerance=pd.Timedelta("10min"),
suffixes=("_oi", "_funding")
)
merged = pd.merge_asof(
merged,
liquidation,
on="time",
direction="nearest",
tolerance=pd.Timedelta("10min")
)
return merged
The merged table may include:
Column
Meaning
time
Timestamp
oi_close
Open interest value
oi_change
Short-term OI change
oi_change_24
24-period OI change
funding_close
Funding rate
funding_z
Funding rate z-score
long_liquidation
Long liquidation amount
short_liquidation
Short liquidation amount
long_liq_z
Long liquidation z-score
short_liq_z
Short liquidation z-score
total_liq_z
Total liquidation z-score
This table becomes the bot’s derivatives market state table.
13. Build a Simple Price Signal
CoinGlass API can provide market data, but many bots still combine derivatives data with price signals.
For simplicity, let’s create a moving average signal.
In production, you may get price candles from:
Your exchange API
CoinGlass spot or futures market endpoints
Your own database
Another market data provider
Example:
def generate_price_signal(price_df):
"""
Simple moving average signal.
price_df must contain a 'close' column.
"""
data = price_df.copy()
data["close"] = pd.to_numeric(data["close"], errors="coerce")
data["ma_fast"] = data["close"].rolling(20).mean()
data["ma_slow"] = data["close"].rolling(60).mean()
latest = data.iloc[-1]
if latest["ma_fast"] > latest["ma_slow"]:
return "BUY"
if latest["ma_fast"] < latest["ma_slow"]:
return "SELL"
return "HOLD"
This signal is intentionally simple. The purpose of the article is not to create a perfect price model, but to show how CoinGlass API data can improve the bot’s market awareness.
14. Build a Derivatives Signal
Now let’s convert the merged derivatives data into a market state signal.
def classify_derivatives_state(row):
funding_z = row.get("funding_z", 0)
long_liq_z = row.get("long_liq_z", 0)
short_liq_z = row.get("short_liq_z", 0)
total_liq_z = row.get("total_liq_z", 0)
oi_change = row.get("oi_change", 0)
if pd.isna(funding_z):
funding_z = 0
if pd.isna(long_liq_z):
long_liq_z = 0
if pd.isna(short_liq_z):
short_liq_z = 0
if pd.isna(total_liq_z):
total_liq_z = 0
if pd.isna(oi_change):
oi_change = 0
if total_liq_z > 3:
return "RISK_OFF"
if funding_z > 2 and oi_change > 0:
return "LONG_CROWDED"
if funding_z < -2 and oi_change > 0:
return "SHORT_CROWDED"
if short_liq_z > 2 and funding_z < 0:
return "SHORT_SQUEEZE"
if long_liq_z > 2 and funding_z > 0:
return "LONG_SQUEEZE"
return "NEUTRAL"
Signal meanings:
Signal
Meaning
NEUTRAL
Market structure is normal
LONG_CROWDED
Long side may be overcrowded
SHORT_CROWDED
Short side may be overcrowded
SHORT_SQUEEZE
Shorts may be getting forced out
LONG_SQUEEZE
Longs may be getting forced out
RISK_OFF
Extreme liquidation environment
This is the core logic of a derivatives-aware bot.
15. Combine Price Signal and Derivatives Signal
Now combine the basic price signal with the CoinGlass-driven market state.
def final_trading_decision(price_signal, derivatives_state):
"""
Combine price signal with derivatives market state.
"""
if derivatives_state == "RISK_OFF":
return "HOLD"
if price_signal == "BUY" and derivatives_state == "LONG_CROWDED":
return "HOLD"
if price_signal == "SELL" and derivatives_state == "SHORT_CROWDED":
return "HOLD"
if price_signal == "BUY" and derivatives_state == "SHORT_SQUEEZE":
return "BUY"
if price_signal == "SELL" and derivatives_state == "LONG_SQUEEZE":
return "SELL"
if derivatives_state in ["NEUTRAL", "SHORT_SQUEEZE", "LONG_SQUEEZE"]:
return price_signal
return "HOLD"
Examples:
Price Signal
Derivatives State
Final Decision
BUY
NEUTRAL
BUY
BUY
LONG_CROWDED
HOLD
SELL
SHORT_CROWDED
HOLD
BUY
SHORT_SQUEEZE
BUY
SELL
LONG_SQUEEZE
SELL
BUY
RISK_OFF
HOLD
SELL
RISK_OFF
HOLD
This logic helps the bot avoid bad trades.
It does not guarantee profit, but it can reduce the likelihood of chasing crowded or unstable market conditions.
16. Add Position Sizing
A trading bot should not only decide whether to trade. It should also decide how much to trade.
def position_size_multiplier(derivatives_state):
multipliers = {
"NEUTRAL": 1.0,
"SHORT_SQUEEZE": 1.0,
"LONG_SQUEEZE": 1.0,
"LONG_CROWDED": 0.4,
"SHORT_CROWDED": 0.4,
"RISK_OFF": 0.0
}
return multipliers.get(derivatives_state, 0.5)
Example:
base_position_size = 1000 # USDT notional
derivatives_state = "LONG_CROWDED"
final_size = base_position_size * position_size_multiplier(derivatives_state)
print(final_size)
If the market is neutral, the bot may use normal size.
If the market is crowded, it may reduce size.
If the market is in risk-off mode, it does not trade.
This is often more useful than simply changing buy/sell signals.
17. Full Bot Framework Example
Below is a simplified full example.
It does not place real orders. Instead, it outputs a final trading decision. This is safer for demonstration and easier to adapt.
import os
import time
import requests
import pandas as pd
from dotenv import load_dotenv
load_dotenv()
BASE_URL = "https://open-api-v4.coinglass.com"
API_KEY = os.getenv("COINGLASS_API_KEY")
if not API_KEY:
raise RuntimeError("Missing COINGLASS_API_KEY environment variable")
HEADERS = {
"CG-API-KEY": API_KEY,
"Accept": "application/json"
}
def request_coinglass(endpoint, params=None):
url = f"{BASE_URL}{endpoint}"
response = requests.get(
url,
headers=HEADERS,
params=params,
timeout=10
)
response.raise_for_status()
return response.json()
def safe_request_coinglass(endpoint, params=None, retries=3, sleep_seconds=2):
last_error = None
for attempt in range(retries):
try:
return request_coinglass(endpoint, params)
except requests.RequestException as error:
last_error = error
print(f"Request failed: attempt {attempt + 1}/{retries}: {error}")
time.sleep(sleep_seconds)
raise last_error
def to_dataframe(raw):
data = raw.get("data", [])
if isinstance(data, dict):
rows = data.get("list", [])
else:
rows = data
df = pd.DataFrame(rows)
if df.empty:
return df
if "time" in df.columns:
df["time"] = pd.to_datetime(df["time"], unit="ms", errors="coerce")
return df
def zscore(series, window=24):
mean = series.rolling(window).mean()
std = series.rolling(window).std()
return (series - mean) / std
def fetch_open_interest(symbol="BTC", interval="1h", limit=100):
endpoint = "/api/futures/openInterest/ohlc-history"
params = {
"symbol": symbol,
"interval": interval,
"limit": limit
}
return safe_request_coinglass(endpoint, params)
def fetch_funding_rate(symbol="BTC", interval="1h", limit=100):
endpoint = "/api/futures/fundingRate/oi-weight-ohlc-history"
params = {
"symbol": symbol,
"interval": interval,
"limit": limit
}
return safe_request_coinglass(endpoint, params)
def fetch_liquidation_history(
symbol="BTC",
exchanges="Binance,OKX,Bybit",
interval="1h",
limit=100
):
endpoint = "/api/futures/liquidation/aggregated-history"
params = {
"exchange_list": exchanges,
"symbol": symbol,
"interval": interval,
"limit": limit
}
return safe_request_coinglass(endpoint, params)
def add_open_interest_features(df):
data = df.copy()
if "close" in data.columns:
data["oi_close"] = pd.to_numeric(data["close"], errors="coerce")
elif "openInterest" in data.columns:
data["oi_close"] = pd.to_numeric(data["openInterest"], errors="coerce")
else:
raise ValueError("No recognizable open interest field found")
data["oi_change"] = data["oi_close"].pct_change()
data["oi_change_24"] = data["oi_close"].pct_change(24)
return data
def add_funding_features(df, window=24):
data = df.copy()
if "close" in data.columns:
data["funding_close"] = pd.to_numeric(data["close"], errors="coerce")
elif "fundingRate" in data.columns:
data["funding_close"] = pd.to_numeric(
data["fundingRate"],
errors="coerce"
)
else:
raise ValueError("No recognizable funding rate field found")
data["funding_z"] = zscore(data["funding_close"], window)
return data
def add_liquidation_features(df, window=24):
data = df.copy()
data = data.rename(columns={
"longLiquidation": "long_liquidation",
"shortLiquidation": "short_liquidation",
"long_liq": "long_liquidation",
"short_liq": "short_liquidation"
})
if "long_liquidation" not in data.columns:
raise ValueError("No long liquidation field found")
if "short_liquidation" not in data.columns:
raise ValueError("No short liquidation field found")
data["long_liquidation"] = pd.to_numeric(
data["long_liquidation"],
errors="coerce"
)
data["short_liquidation"] = pd.to_numeric(
data["short_liquidation"],
errors="coerce"
)
data["long_liq_z"] = zscore(data["long_liquidation"], window)
data["short_liq_z"] = zscore(data["short_liquidation"], window)
data["total_liquidation"] = (
data["long_liquidation"] + data["short_liquidation"]
)
data["total_liq_z"] = zscore(data["total_liquidation"], window)
return data
def prepare_time_column(df):
data = df.copy()
if "time" not in data.columns:
raise ValueError("Missing time column")
data = data.dropna(subset=["time"])
data = data.sort_values("time")
return data
def merge_market_data(oi_df, funding_df, liquidation_df):
oi = prepare_time_column(oi_df)
funding = prepare_time_column(funding_df)
liquidation = prepare_time_column(liquidation_df)
merged = pd.merge_asof(
oi,
funding,
on="time",
direction="nearest",
tolerance=pd.Timedelta("10min"),
suffixes=("_oi", "_funding")
)
merged = pd.merge_asof(
merged,
liquidation,
on="time",
direction="nearest",
tolerance=pd.Timedelta("10min")
)
return merged
def classify_derivatives_state(row):
funding_z = row.get("funding_z", 0)
long_liq_z = row.get("long_liq_z", 0)
short_liq_z = row.get("short_liq_z", 0)
total_liq_z = row.get("total_liq_z", 0)
oi_change = row.get("oi_change", 0)
values = [funding_z, long_liq_z, short_liq_z, total_liq_z, oi_change]
values = [0 if pd.isna(v) else v for v in values]
funding_z, long_liq_z, short_liq_z, total_liq_z, oi_change = values
if total_liq_z > 3:
return "RISK_OFF"
if funding_z > 2 and oi_change > 0:
return "LONG_CROWDED"
if funding_z < -2 and oi_change > 0:
return "SHORT_CROWDED"
if short_liq_z > 2 and funding_z < 0:
return "SHORT_SQUEEZE"
if long_liq_z > 2 and funding_z > 0:
return "LONG_SQUEEZE"
return "NEUTRAL"
def final_trading_decision(price_signal, derivatives_state):
if derivatives_state == "RISK_OFF":
return "HOLD"
if price_signal == "BUY" and derivatives_state == "LONG_CROWDED":
return "HOLD"
if price_signal == "SELL" and derivatives_state == "SHORT_CROWDED":
return "HOLD"
if price_signal == "BUY" and derivatives_state == "SHORT_SQUEEZE":
return "BUY"
if price_signal == "SELL" and derivatives_state == "LONG_SQUEEZE":
return "SELL"
if derivatives_state in ["NEUTRAL", "SHORT_SQUEEZE", "LONG_SQUEEZE"]:
return price_signal
return "HOLD"
def position_size_multiplier(derivatives_state):
multipliers = {
"NEUTRAL": 1.0,
"SHORT_SQUEEZE": 1.0,
"LONG_SQUEEZE": 1.0,
"LONG_CROWDED": 0.4,
"SHORT_CROWDED": 0.4,
"RISK_OFF": 0.0
}
return multipliers.get(derivatives_state, 0.5)
def run_bot_once(symbol="BTC"):
oi_raw = fetch_open_interest(symbol=symbol, interval="1h", limit=100)
funding_raw = fetch_funding_rate(symbol=symbol, interval="1h", limit=100)
liquidation_raw = fetch_liquidation_history(
symbol=symbol,
interval="1h",
limit=100
)
oi_df = add_open_interest_features(to_dataframe(oi_raw))
funding_df = add_funding_features(to_dataframe(funding_raw))
liquidation_df = add_liquidation_features(to_dataframe(liquidation_raw))
market_df = merge_market_data(oi_df, funding_df, liquidation_df)
if market_df.empty:
raise ValueError("Merged market data is empty")
latest = market_df.iloc[-1]
# Example only. Replace this with your real price signal.
price_signal = "BUY"
derivatives_state = classify_derivatives_state(latest)
final_decision = final_trading_decision(price_signal, derivatives_state)
base_position_size = 1000
multiplier = position_size_multiplier(derivatives_state)
final_position_size = base_position_size * multiplier
result = {
"symbol": symbol,
"time": latest["time"],
"price_signal": price_signal,
"derivatives_state": derivatives_state,
"final_decision": final_decision,
"position_size": final_position_size
}
return result
if __name__ == "__main__":
result = run_bot_once("BTC")
print("Bot result:")
for key, value in result.items():
print(f"{key}: {value}")
This bot framework does not place orders. That is intentional.
Before connecting any strategy to real trading, you should:
Backtest it
Paper trade it
Add exchange execution logic
Add risk limits
Add error handling
Add logs
Add monitoring
Start with small position size
18. How to Add Exchange Execution
Once the CoinGlass API side works, you can connect the decision output to an exchange API.
The execution layer should be separate from the signal layer.
Example structure:
def execute_trade(decision, symbol, position_size):
"""
Placeholder execution function.
Replace with your exchange API logic.
"""
if decision == "BUY":
print(f"Place BUY order for {symbol}, size={position_size}")
elif decision == "SELL":
print(f"Place SELL order for {symbol}, size={position_size}")
else:
print(f"No trade for {symbol}")
Then:
result = run_bot_once("BTC")
execute_trade(
decision=result["final_decision"],
symbol=result["symbol"],
position_size=result["position_size"]
)
In production, the execution function should handle:
Order type
Quantity precision
Minimum notional
Slippage
Leverage
Margin mode
Reduce-only orders
Stop loss
Take profit
Position checking
Order status confirmation
Never connect a strategy directly to live execution without safety checks.
19. Risk Management Rules
A trading bot without risk management is not a trading system. It is just an automated order sender.
At minimum, your bot should include:
Rule
Purpose
Max position size
Prevent oversized trades
Max daily loss
Stop trading after major losses
Max open positions
Avoid overexposure
Stop loss
Limit downside
Take profit
Lock gains
Cooldown period
Avoid overtrading
Risk-off mode
Stop trading during extreme events
API failure mode
Avoid trading with stale data
Example risk filter:
def risk_filter(account_state, market_state):
"""
Example risk control logic.
"""
if account_state["daily_loss_pct"] < -3:
return "STOP_TRADING"
if account_state["open_positions"] >= account_state["max_positions"]:
return "NO_NEW_POSITIONS"
if market_state["derivatives_state"] == "RISK_OFF":
return "NO_NEW_POSITIONS"
return "ALLOW"
Risk management should override signal generation.
A good rule is:
Signal decides what you want to do.
Risk decides whether you are allowed to do it.
20. Backtesting the Strategy
Before using real money, backtest the bot.
A proper backtest should include:
Price candles
Open interest history
Funding rate history
Liquidation history
Trading fees
Slippage
Funding payments
Latency assumptions
Position size rules
Stop loss logic
Market regime changes
A basic backtest loop may look like this:
def backtest(market_df, price_signals):
equity = 10000
position = 0
trades = []
for i in range(len(market_df)):
row = market_df.iloc[i]
price_signal = price_signals[i]
derivatives_state = classify_derivatives_state(row)
decision = final_trading_decision(price_signal, derivatives_state)
size_multiplier = position_size_multiplier(derivatives_state)
trades.append({
"time": row["time"],
"price_signal": price_signal,
"derivatives_state": derivatives_state,
"decision": decision,
"size_multiplier": size_multiplier
})
return pd.DataFrame(trades)
This is only a skeleton. A real backtest must calculate:
Entry price
Exit price
PnL
Fees
Funding payments
Drawdown
Sharpe ratio
Win rate
Average profit/loss
Maximum loss
Exposure time
Do not skip this step.
A strategy that looks good in a single example may fail across different market regimes.
21. Production Checklist
Before putting a CoinGlass API-powered trading bot into production, use this checklist.
Checklist Item
Why It Matters
Confirm latest API endpoints
API routes and parameters may change
Confirm response fields
Field names may differ by endpoint
Store API key securely
Prevent credential leaks
Add request retries
Handle temporary errors
Add timeout handling
Prevent stuck processes
Add data validation
Avoid trading on broken data
Add stale data checks
Avoid using old signals
Add rate limit handling
Prevent API blocking
Add logs
Debug strategy behavior
Add paper trading
Validate real-time behavior
Add risk limits
Prevent catastrophic loss
Add monitoring alerts
Detect failures quickly
Add manual shutdown
Stop bot during emergencies
Start small
Reduce deployment risk
Example stale data check:
def check_data_freshness(latest_time, max_age_minutes=90):
now = pd.Timestamp.utcnow()
if latest_time.tzinfo is None:
latest_time = latest_time.tz_localize("UTC")
age = now - latest_time
if age > pd.Timedelta(minutes=max_age_minutes):
raise ValueError(f"Data is stale: latest data age is {age}")
return True
22. Common Mistakes
Mistake 1: Using Funding Rate as a Standalone Signal
Funding rate should not be used alone.
Wrong:
Funding high → short
Funding low → long
Better:
Funding high → long side may be crowded
Funding low → short side may be crowded
Confirm with OI, price, and liquidation data
Mistake 2: Entering Immediately After Liquidations
A liquidation spike can mean a reversal, but it can also mean trend continuation.
You need to check:
Did price reclaim the level?
Did open interest drop?
Did funding normalize?
Did volume fade?
Did the liquidation cascade continue?
Mistake 3: Ignoring Open Interest
Price without OI context can be misleading.
Price Move
OI Move
Possible Meaning
Up
Up
New longs or new positions support the move
Up
Down
Shorts closing
Down
Up
New shorts entering
Down
Down
Longs closing or liquidating
Mistake 4: Overfitting Too Many Indicators
Start simple.
A practical first version can use:
Price signal
+ OI confirmation
+ Funding filter
+ Liquidation risk filter
+ Position sizing rule
Then test improvements one by one.
Mistake 5: No Kill Switch
Every live bot needs a manual and automatic kill switch.
Examples:
Stop trading if API data is stale.
Stop trading if daily loss exceeds threshold.
Stop trading if liquidation risk is extreme.
Stop trading if exchange order API behaves unexpectedly.
23. Strategy Templates You Can Build with CoinGlass API
Template 1: Trend Confirmation Bot
Goal:
Trade only when price trend is supported by derivatives data.
Rules:
Condition
Requirement
Price
Breakout or moving average trend
Open Interest
Rising gradually
Funding Rate
Not extreme
Liquidations
No abnormal opposite-side risk
Decision
Allow trade
Best for:
BTC trend strategies
ETH momentum strategies
Multi-asset futures bots
Template 2: Short Squeeze Bot
Goal:
Detect possible short squeeze setups.
Rules:
Condition
Requirement
Funding Rate
Negative
Open Interest
High or rising
Price
Breaks resistance
Short Liquidations
Rising
Decision
Allow long signal
Best for:
Breakout bots
Momentum bots
Event-driven strategies
Template 3: Long Squeeze Risk Filter
Goal:
Avoid long exposure when the long side is overcrowded.
Rules:
Condition
Requirement
Funding Rate
Very positive
Open Interest
Rising
Price
Breaks support
Long Liquidations
Rising
Decision
Exit, reduce, or avoid longs
Best for:
Grid bots
Long-biased bots
Leveraged futures strategies
Template 4: Funding Rate Arbitrage Monitor
Goal:
Detect cross-exchange funding rate opportunities.
Rules:
Condition
Requirement
Funding difference
Large enough
Liquidity
Sufficient
Open Interest
Stable
Liquidation risk
Not extreme
Decision
Alert or evaluate trade
Best for:
Market-neutral strategies
Funding capture bots
Arbitrage dashboards
Template 5: Risk-Off Detector
Goal:
Pause trading during extreme derivatives stress.
Rules:
Condition
Trigger
Total liquidation z-score
Above 3
Funding z-score
Extreme
OI change
Abnormal
Price volatility
High
Decision
Pause trading
Best for:
All leveraged bots
Portfolio risk systems
Multi-strategy trading platforms
24. How to Expand the Bot
After building the first version, you can expand it with more CoinGlass API data.
Add Long/Short Ratio
Use long/short ratio to detect market sentiment imbalance.
Possible rule:
If long/short ratio is extremely long
AND funding is positive
AND OI is rising
THEN reduce long exposure.
Add Taker Buy/Sell Volume
Use taker buy/sell volume to confirm aggressive flow.
Possible rule:
If price breaks resistance
AND taker buy volume rises
AND short liquidations rise
THEN confirm short squeeze.
Add Liquidation Heatmap
Use liquidation heatmap data to identify zones where forced liquidations may occur.
Possible rule:
If price approaches large liquidation cluster
THEN reduce leverage or tighten stop.
Add Order Book Data
Use order book data for execution quality.
Possible rule:
If order book depth is thin
THEN reduce order size or use limit orders.
Add ETF Flow Data
For BTC and ETH, ETF flow data can help detect broader market demand.
Possible rule:
If ETF inflows are strong
AND derivatives data is not overheated
THEN increase bullish confidence.
25. Final Thoughts
Building a crypto trading bot is not just about coding buy and sell rules.
A strong bot needs to understand market conditions.
Price tells you what happened.
Derivatives data helps explain why it happened.
CoinGlass API can help trading bots move from simple price-based automation to a more complete market-aware system by providing data such as:
Open interest
Funding rate
Liquidations
Long/short ratio
Taker buy/sell volume
Order book data
Liquidation heatmap
ETF flow data
Options data
A basic bot might say:
Price is above the moving average, so buy.
A better bot says:
Price is above the moving average.
Open interest is rising.
Funding rate is neutral.
Liquidations are normal.
Market structure is healthy.
Buy signal is allowed.
Or:
Price is above the moving average.
But funding is extremely positive.
Open interest is rising too fast.
Long side is crowded.
Do not chase.
That is the difference between a simple script and a more intelligent trading system.
No API can guarantee profitable trading. CoinGlass API does not replace strategy design, risk management, execution quality, or backtesting.
But it can provide the derivatives market intelligence that many trading bots are missing.
If you are building a crypto futures or perpetual trading bot, CoinGlass API is one of the most practical ways to add market structure awareness to your system.
📰Originally published at dev.to
B
Blizine Admin
View Profile Staff Writer