⚠️ 运行脚本: 必须先 cd 到本 SKILL.md 所在目录再执行。示例:
cd ~/.openclaw/workspace/skills/aicoin-freqtrade && node scripts/ft-deploy.mjs ...
AiCoin Freqtrade
Freqtrade strategy creation, backtesting, and deployment powered by AiCoin Open API.
Critical Rules
- ALWAYS use
ft-deploy.mjs backtestfor backtesting. NEVER write custom backtest scripts. NEVER use simulated/fabricated data. - ALWAYS use
ft-deploy.mjs deployfor deployment. NEVER use Docker. NEVER manually runfreqtradecommands. - NEVER manually edit Freqtrade config files. Use
ft-deploy.mjsactions. - NEVER manually run
freqtrade trade,freqtrade status,freqtrade backtesting,source .venv/bin/activate, orpip install freqtrade. Always use ft-deploy.mjs or ft.mjs instead. - ACTIVELY use AiCoin data in strategies. Check what data the user's API key supports and integrate it. Don't only use basic indicators when richer data is available.
- Freqtrade 不支持网格策略(grid)。 用户问网格时,说明限制并建议用趋势跟踪或区间策略替代。
Two Ways to Create Strategies
Option A: Quick Generator (for simple strategies)
create_strategy generates a ready-to-backtest strategy file with selected indicators and optional AiCoin data:
node scripts/ft-deploy.mjs create_strategy '{"name":"MACDStrategy","timeframe":"15m","indicators":["macd","rsi","atr"]}'
node scripts/ft-deploy.mjs create_strategy '{"name":"WhaleStrat","timeframe":"15m","indicators":["rsi","macd"],"aicoin_data":["funding_rate","ls_ratio"]}'
Available indicators: rsi, bb, ema, sma, macd, stochastic/kdj, atr, adx, cci, williams_r, vwap, ichimoku, volume_sma, obv
Option B: Write Custom Strategy Code (for complex/custom strategies)
When users need custom logic beyond what create_strategy offers, write a Python strategy file directly. Use the AiCoin Python SDK (aicoin_data.py, auto-installed at ~/.freqtrade/user_data/strategies/) to integrate real market data.
Strategy file location: ~/.freqtrade/user_data/strategies/YourStrategyName.py
AiCoin Python SDK Reference
from aicoin_data import AiCoinData, ccxt_to_aicoin
ac = AiCoinData(cache_ttl=300) # Auto-loads API keys from .env
# Convert CCXT pair to AiCoin symbol
symbol = ccxt_to_aicoin("BTC/USDT:USDT", "binance") # → "btcswapusdt:binance"
# ── Free tier (no key needed) ──
ac.coin_ticker("bitcoin") # Real-time price
ac.kline(symbol, period="3600") # K-line data (period in seconds)
ac.hot_coins("market") # Trending coins
# ── 基础版 ($29/mo) ──
ac.funding_rate(symbol) # Funding rate history
ac.funding_rate(symbol, weighted=True) # Volume-weighted cross-exchange rate
ac.ls_ratio() # Aggregated long/short ratio
# ── 标准版 ($79/mo) ──
ac.big_orders(symbol) # Whale/large orders
ac.agg_trades(symbol) # Aggregated large trades
# ── 高级版 ($299/mo) ──
ac.liquidation_map(symbol, cycle="24h") # Liquidation heatmap
ac.liquidation_history(symbol) # Liquidation history
# ── 专业版 ($699/mo) ──
ac.open_interest("BTC", interval="15m") # Aggregated open interest
ac.ai_analysis(["BTC"]) # AI-powered analysis
Complete Strategy Template (copy and customize)
# MyCustomStrategy - Description
# Uses AiCoin data in live/dry_run mode
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
from pandas import DataFrame
import logging, time
logger = logging.getLogger(__name__)
class MyCustomStrategy(IStrategy):
INTERFACE_VERSION = 3
timeframe = '15m'
can_short = True
minimal_roi = {"0": 0.05, "60": 0.03, "120": 0.01}
stoploss = -0.05
trailing_stop = True
trailing_stop_positive = 0.02
trailing_stop_positive_offset = 0.03
# Hyperopt parameters
rsi_buy = IntParameter(20, 40, default=30, space='buy')
rsi_sell = IntParameter(60, 80, default=70, space='sell')
# AiCoin data cache
_ac_funding_rate = 0.0
_ac_ls_ratio = 0.5
_ac_whale_signal = 0.0
_ac_last_update = 0.0
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# === Technical Indicators (always available) ===
# RSI
delta = dataframe['close'].diff()
gain = delta.clip(lower=0).rolling(window=14).mean()
loss = (-delta.clip(upper=0)).rolling(window=14).mean()
rs = gain / loss
dataframe['rsi'] = 100 - (100 / (1 + rs))
# MACD
ema12 = dataframe['close'].ewm(span=12, adjust=False).mean()
ema26 = dataframe['close'].ewm(span=26, adjust=False).mean()
dataframe['macd'] = ema12 - ema26
dataframe['macd_signal'] = dataframe['macd'].ewm(span=9, adjust=False).mean()
# EMA
dataframe['ema_fast'] = dataframe['close'].ewm(span=8, adjust=False).mean()
dataframe['ema_slow'] = dataframe['close'].ewm(span=21, adjust=False).mean()
# === AiCoin Data (live/dry_run only) ===
dataframe['funding_rate'] = 0.0
dataframe['ls_ratio'] = 0.5
dataframe['whale_signal'] = 0.0
if self.dp and self.dp.runmode.value in ('live', 'dry_run'):
now = time.time()
if now - self._ac_last_update > 300: # Update every 5 min
self._update_aicoin_data(metadata)
self._ac_last_update = now
# Apply latest AiCoin data to current candle
dataframe.iloc[-1, dataframe.columns.get_loc('funding_rate')] = self._ac_funding_rate
dataframe.iloc[-1, dataframe.columns.get_loc('ls_ratio')] = self._ac_ls_ratio
dataframe.iloc[-1, dataframe.columns.get_loc('whale_signal')] = self._ac_whale_signal
return dataframe
def _update_aicoin_data(self, metadata: dict):
"""Fetch latest AiCoin data. Called every 5 min in live mode."""
try:
import sys, os
_sd = os.path.dirname(os.path.abspath(__file__))
if _sd not in sys.path:
sys.path.insert(0, _sd)
from aicoin_data import AiCoinData, ccxt_to_aicoin
ac = AiCoinData(cache_ttl=300)
pair = metadata.get('pair', 'BTC/USDT:USDT')
exchange = self.config.get('exchange', {}).get('name', 'binance')
symbol = ccxt_to_aicoin(pair, exchange)
# Funding rate (基础版)
try:
data = ac.funding_rate(symbol, weighted=True, limit='5')
items = data.get('data', [])
if isinstance(items, list) and items:
latest = items[0]
if isinstance(latest, dict) and 'close' in latest:
self._ac_funding_rate = float(latest['close']) * 100
except Exception as e:
logger.debug(f"AiCoin funding_rate unavailable: {e}")
# Long/short ratio (基础版)
try:
ls = ac.ls_ratio()
detail = ls.get('data', {}).get('detail', {})
if detail:
ratio = float(detail.get('last', 1.0))
self._ac_ls_ratio = max(0.0, min(1.0, ratio / (1.0 + ratio)))
except Exception as e:
logger.debug(f"AiCoin ls_ratio unavailable: {e}")
# Whale orders (标准版)
try:
orders = ac.big_orders(symbol)
if 'data' in orders and isinstance(orders['data'], list):
buy_vol = sum(float(o.get('amount', 0)) for o in orders['data']
if o.get('side', '').lower() in ('buy', 'bid', 'long'))
sell_vol = sum(float(o.get('amount', 0)) for o in orders['data']
if o.get('side', '').lower() in ('sell', 'ask', 'short'))
total = buy_vol + sell_vol
if total > 0:
self._ac_whale_signal = (buy_vol - sell_vol) / total
except Exception as e:
logger.debug(f"AiCoin big_orders unavailable: {e}")
except ImportError:
logger.warning("aicoin_data module not found. Run ft-deploy.mjs deploy to install.")
except Exception as e:
logger.warning(f"AiCoin data error: {e}")
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Long: RSI oversold + MACD bullish + AiCoin confirmations
dataframe.loc[
(dataframe['rsi'] < self.rsi_buy.value) &
(dataframe['macd'] > dataframe['macd_signal']) &
(dataframe['ema_fast'] > dataframe['ema_slow']) &
(dataframe['ls_ratio'] <= 0.55) & # More shorts = contrarian long
(dataframe['whale_signal'] >= -0.3) & # Whales not heavily selling
(dataframe['volume'] > 0),
'enter_long'] = 1
# Short: RSI overbought + MACD bearish + AiCoin confirmations
dataframe.loc[
(dataframe['rsi'] > self.rsi_sell.value) &
(dataframe['macd'] < dataframe['macd_signal']) &
(dataframe['ema_fast'] < dataframe['ema_slow']) &
(dataframe['ls_ratio'] >= 0.45) & # More longs = contrarian short
(dataframe['whale_signal'] <= 0.3) & # Whales not heavily buying
(dataframe['volume'] > 0),
'enter_short'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[(dataframe['rsi'] > 70), 'exit_long'] = 1
dataframe.loc[(dataframe['rsi'] < 30), 'exit_short'] = 1
return dataframe
AiCoin Data Integration Patterns
Use these patterns to integrate specific AiCoin data into entry/exit conditions:
| AiCoin Data | Signal Logic | Tier |
|---|---|---|
funding_rate | Rate > 0.01% → market over-leveraged long → short signal; Rate < -0.01% → long signal | 基础版 |
ls_ratio | Ratio < 0.45 (more shorts) → contrarian long; Ratio > 0.55 (more longs) → contrarian short | 基础版 |
big_orders | (buy_vol - sell_vol) / total > 0.3 → whale buying → long; < -0.3 → short | 标准版 |
open_interest | OI rising + price rising = healthy trend; OI rising + price falling = weak, likely reversal | 专业版 |
liquidation_map | More short liquidations above → short squeeze likely → long; vice versa | 高级版 |
Key Rule: Backtest Behavior
AiCoin real-time data is NOT available for historical periods. In backtest mode:
- AiCoin columns use default values (funding_rate=0.0, ls_ratio=0.5, whale_signal=0.0)
- This means backtest results reflect technical indicators only
- Live/dry_run trading uses real AiCoin data, which should improve performance vs backtest
Always explain this to the user when showing backtest results.
Quick Reference
| Task | Command |
|---|---|
| Quick-generate strategy | node scripts/ft-deploy.mjs create_strategy '{"name":"MyStrat","timeframe":"15m","indicators":["rsi","macd"],"aicoin_data":["funding_rate"]}' |
| Backtest | node scripts/ft-deploy.mjs backtest '{"strategy":"MyStrat","timeframe":"1h","timerange":"20250101-20260301","pairs":["ETH/USDT:USDT"]}' |
| Deploy (dry-run) | node scripts/ft-deploy.mjs deploy '{"strategy":"MyStrat","pairs":["BTC/USDT:USDT"]}' |
| Deploy (live) | node scripts/ft-deploy.mjs deploy '{"strategy":"MyStrat","dry_run":false,"pairs":["BTC/USDT:USDT"]}' |
| Hyperopt | node scripts/ft-deploy.mjs hyperopt '{"strategy":"MyStrat","timeframe":"1h","timerange":"20250101-20260301","epochs":100}' |
| Strategy list | node scripts/ft-deploy.mjs strategy_list |
| Bot status | node scripts/ft-deploy.mjs status |
| Bot logs | node scripts/ft-deploy.mjs logs '{"lines":50}' |
Setup
Prerequisites: Python 3.11+ and git.
.env auto-loaded from (first found wins): cwd → ~/.openclaw/workspace/.env → ~/.openclaw/.env
Exchange keys (for live/dry-run):
BINANCE_API_KEY=xxx
BINANCE_API_SECRET=xxx
AiCoin API key (for AiCoin data in strategies):
AICOIN_ACCESS_KEY_ID=your-key-id
AICOIN_ACCESS_SECRET=your-secret
Get at https://www.aicoin.com/opendata
Scripts
ft-deploy.mjs — Deployment & Strategy
| Action | Params |
|---|---|
check | None |
deploy | {"strategy":"MACDKDJStrategy","dry_run":true,"pairs":["BTC/USDT:USDT"]} — strategy 必填,指定策略名 |
backtest | {"strategy":"Name","timeframe":"1h","timerange":"20250101-20260301","pairs":["ETH/USDT:USDT"]} — pairs 可选,默认用 config 中的交易对 |
hyperopt | {"strategy":"Name","timeframe":"1h","epochs":100} |
create_strategy | {"name":"Name","timeframe":"15m","indicators":["rsi","macd"],"aicoin_data":["funding_rate"]} |
strategy_list | None |
backtest_results | None — lists recent backtest result files |
start / stop / status / logs | None / {"lines":50} |
ft.mjs — Bot Control (requires running process)
ping, start, stop, balance, profit, trades_open, trades_history, force_enter, force_exit, daily, weekly, monthly, stats
ft-dev.mjs — Dev Tools (requires running process)
backtest_start, backtest_status, candles_live, candles_analyzed, strategy_list, strategy_get
Cross-Skill References
| Need | Use |
|---|---|
| Prices, K-lines, market data | aicoin-market |
| Exchange trading (buy/sell) | aicoin-trading |
| Hyperliquid whale tracking | aicoin-hyperliquid |
Paid Feature Guide
When 304/403: Do NOT retry. Guide the user:
| Tier | Price | Data for Strategies |
|---|---|---|
| 免费版 | $0 | Pure technical indicators |
| 基础版 | $29/mo | + funding_rate, ls_ratio |
| 标准版 | $79/mo | + big_orders, agg_trades |
| 高级版 | $299/mo | + liquidation_map |
| 专业版 | $699/mo | + open_interest, ai_analysis |
Configure: AICOIN_ACCESS_KEY_ID + AICOIN_ACCESS_SECRET in .env