Merge pull request #12 from mindesbunister/copilot/add-fartcoin-perp-market
Add FARTCOIN-PERP market with percentage-based position sizing
This commit is contained in:
@@ -85,6 +85,9 @@ export async function GET() {
|
||||
ETHEREUM_POSITION_SIZE: parseFloat(env.ETHEREUM_POSITION_SIZE || '4'),
|
||||
ETHEREUM_LEVERAGE: parseFloat(env.ETHEREUM_LEVERAGE || '1'),
|
||||
ETHEREUM_USE_PERCENTAGE_SIZE: env.ETHEREUM_USE_PERCENTAGE_SIZE === 'true',
|
||||
FARTCOIN_ENABLED: env.FARTCOIN_ENABLED === 'true',
|
||||
FARTCOIN_POSITION_SIZE: parseFloat(env.FARTCOIN_POSITION_SIZE || '20'),
|
||||
FARTCOIN_LEVERAGE: parseFloat(env.FARTCOIN_LEVERAGE || '10'),
|
||||
|
||||
// Risk management
|
||||
STOP_LOSS_PERCENT: parseFloat(env.STOP_LOSS_PERCENT || '-1.5'),
|
||||
@@ -161,6 +164,9 @@ export async function POST(request: NextRequest) {
|
||||
ETHEREUM_ENABLED: settings.ETHEREUM_ENABLED.toString(),
|
||||
ETHEREUM_POSITION_SIZE: settings.ETHEREUM_POSITION_SIZE.toString(),
|
||||
ETHEREUM_LEVERAGE: settings.ETHEREUM_LEVERAGE.toString(),
|
||||
FARTCOIN_ENABLED: settings.FARTCOIN_ENABLED.toString(),
|
||||
FARTCOIN_POSITION_SIZE: settings.FARTCOIN_POSITION_SIZE.toString(),
|
||||
FARTCOIN_LEVERAGE: settings.FARTCOIN_LEVERAGE.toString(),
|
||||
|
||||
// Risk management
|
||||
STOP_LOSS_PERCENT: settings.STOP_LOSS_PERCENT.toString(),
|
||||
|
||||
@@ -23,6 +23,9 @@ interface TradingSettings {
|
||||
ETHEREUM_POSITION_SIZE: number
|
||||
ETHEREUM_LEVERAGE: number
|
||||
ETHEREUM_USE_PERCENTAGE_SIZE: boolean
|
||||
FARTCOIN_ENABLED: boolean
|
||||
FARTCOIN_POSITION_SIZE: number
|
||||
FARTCOIN_LEVERAGE: number
|
||||
|
||||
// Risk management
|
||||
STOP_LOSS_PERCENT: number
|
||||
@@ -467,6 +470,81 @@ export default function SettingsPage() {
|
||||
})()}
|
||||
</Section>
|
||||
|
||||
{/* FARTCOIN Section */}
|
||||
<Section title="🎈 Fartcoin (FARTCOIN-PERP)" description="Individual settings for Fartcoin perpetual trading (PROFIT MODE)">
|
||||
<div className="mb-4 p-3 bg-pink-500/10 border border-pink-500/30 rounded-lg">
|
||||
<p className="text-sm text-pink-400">
|
||||
Enable/disable FARTCOIN trading with percentage-based position sizing for profit generation. Uses % of portfolio instead of fixed USD amounts.
|
||||
</p>
|
||||
<div className="mt-2 inline-flex items-center gap-2 px-3 py-1 bg-purple-500/20 rounded-full">
|
||||
<span className="text-xs font-bold text-purple-300">PERCENTAGE-BASED</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between p-4 bg-slate-700/30 rounded-lg mb-4">
|
||||
<div className="flex-1">
|
||||
<div className="text-white font-medium mb-1">🟢 Enable Fartcoin Trading</div>
|
||||
<div className="text-slate-400 text-sm">
|
||||
Accept FARTCOIN-PERP trade signals from TradingView
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => updateSetting('FARTCOIN_ENABLED', !settings.FARTCOIN_ENABLED)}
|
||||
className={`relative inline-flex h-8 w-14 items-center rounded-full transition-colors ${
|
||||
settings.FARTCOIN_ENABLED ? 'bg-green-500' : 'bg-slate-600'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-6 w-6 transform rounded-full bg-white transition-transform ${
|
||||
settings.FARTCOIN_ENABLED ? 'translate-x-7' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<Setting
|
||||
label="FARTCOIN Position Size (% of Portfolio)"
|
||||
value={settings.FARTCOIN_POSITION_SIZE}
|
||||
onChange={(v) => updateSetting('FARTCOIN_POSITION_SIZE', v)}
|
||||
min={1}
|
||||
max={100}
|
||||
step={1}
|
||||
description={`Percentage of your portfolio to allocate per FARTCOIN trade. With ${settings.FARTCOIN_LEVERAGE}x leverage = ${(settings.FARTCOIN_POSITION_SIZE * settings.FARTCOIN_LEVERAGE).toFixed(0)}% notional exposure. Example: 20% × $${collateral.toFixed(0)} = $${(settings.FARTCOIN_POSITION_SIZE / 100 * collateral).toFixed(2)} base.`}
|
||||
/>
|
||||
<Setting
|
||||
label="FARTCOIN Leverage"
|
||||
value={settings.FARTCOIN_LEVERAGE}
|
||||
onChange={(v) => updateSetting('FARTCOIN_LEVERAGE', v)}
|
||||
min={1}
|
||||
max={10}
|
||||
step={1}
|
||||
description="Leverage multiplier for Fartcoin positions (max 10x based on Drift margin requirements)."
|
||||
/>
|
||||
{(() => {
|
||||
const fartcoinRisk = {
|
||||
maxLoss: (settings.FARTCOIN_POSITION_SIZE / 100 * collateral * settings.FARTCOIN_LEVERAGE) * 0.015,
|
||||
fullWin: (settings.FARTCOIN_POSITION_SIZE / 100 * collateral * settings.FARTCOIN_LEVERAGE) * 0.018,
|
||||
}
|
||||
return (
|
||||
<div className="p-4 bg-slate-700/50 rounded-lg">
|
||||
<div className="text-sm text-slate-300 mb-2">FARTCOIN Risk/Reward (% of Portfolio)</div>
|
||||
<div className="flex gap-4 text-xs">
|
||||
<div>
|
||||
<span className="text-red-400">Max Loss: </span>
|
||||
<span className="text-white font-bold">${fartcoinRisk.maxLoss.toFixed(2)}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-green-400">Full Win: </span>
|
||||
<span className="text-white font-bold">${fartcoinRisk.fullWin.toFixed(2)}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-purple-400">R:R </span>
|
||||
<span className="text-white font-bold">1:{(fartcoinRisk.fullWin / fartcoinRisk.maxLoss).toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})()}
|
||||
</Section>
|
||||
|
||||
{/* Global Position Sizing (Fallback) */}
|
||||
<Section title="💰 Global Position Sizing (Fallback)" description="Default settings for symbols without specific config (e.g., BTC)">
|
||||
<div className="mb-4 p-3 bg-yellow-500/10 border border-yellow-500/30 rounded-lg">
|
||||
|
||||
@@ -28,6 +28,7 @@ export interface TradingConfig {
|
||||
// Per-symbol settings
|
||||
solana?: SymbolSettings
|
||||
ethereum?: SymbolSettings
|
||||
fartcoin?: SymbolSettings
|
||||
|
||||
// Risk management (as percentages of entry price - LEGACY, used as fallback)
|
||||
stopLossPercent: number // Negative number (e.g., -1.5)
|
||||
@@ -135,6 +136,12 @@ export const DEFAULT_TRADING_CONFIG: TradingConfig = {
|
||||
leverage: 1, // 1x leverage = $4 notional
|
||||
usePercentageSize: false,
|
||||
},
|
||||
fartcoin: {
|
||||
enabled: false, // DISABLED BY DEFAULT
|
||||
positionSize: 20, // 20% of portfolio (for profit generation)
|
||||
leverage: 10, // 10x leverage
|
||||
usePercentageSize: true, // PERCENTAGE-BASED (not fixed USD)
|
||||
},
|
||||
|
||||
// Risk parameters (LEGACY FALLBACK - used when ATR unavailable)
|
||||
stopLossPercent: -1.5, // Fallback: -1.5% if no ATR
|
||||
@@ -234,6 +241,14 @@ export const SUPPORTED_MARKETS: Record<string, MarketConfig> = {
|
||||
positionSize: 40, // $40 base capital
|
||||
leverage: 1, // 1x leverage = $40 total exposure
|
||||
},
|
||||
'FARTCOIN-PERP': {
|
||||
symbol: 'FARTCOIN-PERP',
|
||||
driftMarketIndex: 22,
|
||||
pythPriceFeedId: '2sZomfWMDuQLcFak3nuharXorHrZ3hK8iaML6ZGSHtso',
|
||||
minOrderSize: 1, // 1 FARTCOIN minimum
|
||||
tickSize: 0.0001,
|
||||
// Use per-symbol config below
|
||||
},
|
||||
}
|
||||
|
||||
// Map TradingView symbols to Drift markets
|
||||
@@ -243,6 +258,7 @@ export function normalizeTradingViewSymbol(tvSymbol: string): string {
|
||||
if (upper.includes('SOL')) return 'SOL-PERP'
|
||||
if (upper.includes('BTC')) return 'BTC-PERP'
|
||||
if (upper.includes('ETH')) return 'ETH-PERP'
|
||||
if (upper.includes('FARTCOIN')) return 'FARTCOIN-PERP'
|
||||
|
||||
// Default to SOL if unknown
|
||||
console.warn(`Unknown symbol ${tvSymbol}, defaulting to SOL-PERP`)
|
||||
@@ -277,6 +293,14 @@ export function getPositionSizeForSymbol(symbol: string, baseConfig: TradingConf
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol === 'FARTCOIN-PERP' && baseConfig.fartcoin) {
|
||||
return {
|
||||
size: baseConfig.fartcoin.positionSize,
|
||||
leverage: baseConfig.fartcoin.leverage,
|
||||
enabled: baseConfig.fartcoin.enabled,
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to market-specific config, then global config
|
||||
const marketConfig = getMarketConfig(symbol)
|
||||
return {
|
||||
@@ -352,6 +376,13 @@ export async function getActualPositionSizeForSymbol(
|
||||
enabled: baseConfig.ethereum.enabled,
|
||||
}
|
||||
usePercentage = baseConfig.ethereum.usePercentageSize ?? false
|
||||
} else if (symbol === 'FARTCOIN-PERP' && baseConfig.fartcoin) {
|
||||
symbolSettings = {
|
||||
size: baseConfig.fartcoin.positionSize,
|
||||
leverage: baseConfig.fartcoin.leverage,
|
||||
enabled: baseConfig.fartcoin.enabled,
|
||||
}
|
||||
usePercentage = baseConfig.fartcoin.usePercentageSize ?? false
|
||||
} else {
|
||||
// Fallback to market-specific or global config
|
||||
const marketConfig = getMarketConfig(symbol)
|
||||
@@ -502,6 +533,16 @@ export function getConfigFromEnv(): Partial<TradingConfig> {
|
||||
? process.env.ETHEREUM_USE_PERCENTAGE_SIZE === 'true'
|
||||
: false,
|
||||
},
|
||||
fartcoin: {
|
||||
enabled: process.env.FARTCOIN_ENABLED === 'true',
|
||||
positionSize: process.env.FARTCOIN_POSITION_SIZE
|
||||
? parseFloat(process.env.FARTCOIN_POSITION_SIZE)
|
||||
: 20,
|
||||
leverage: process.env.FARTCOIN_LEVERAGE
|
||||
? parseInt(process.env.FARTCOIN_LEVERAGE)
|
||||
: 10,
|
||||
usePercentageSize: process.env.FARTCOIN_USE_PERCENTAGE_SIZE !== 'false', // Default true
|
||||
},
|
||||
leverage: process.env.LEVERAGE
|
||||
? parseInt(process.env.LEVERAGE)
|
||||
: undefined,
|
||||
|
||||
149
docs/markets/FARTCOIN-PERP.md
Normal file
149
docs/markets/FARTCOIN-PERP.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# FARTCOIN-PERP Market Configuration
|
||||
|
||||
## Market Details
|
||||
- **Market Index**: 22
|
||||
- **Symbol**: FARTCOIN-PERP
|
||||
- **Oracle**: `2sZomfWMDuQLcFak3nuharXorHrZ3hK8iaML6ZGSHtso`
|
||||
- **Min Order Size**: 1 FARTCOIN
|
||||
- **Tick Size**: $0.0001 (price precision)
|
||||
- **Initial Margin Ratio**: 10% (max 10x leverage)
|
||||
- **Maintenance Margin Ratio**: 5%
|
||||
|
||||
## Configuration Mode
|
||||
- **Mode**: PROFIT GENERATION 💰
|
||||
- **Position Sizing**: Percentage-based (20% of portfolio default)
|
||||
- **Default Leverage**: 10x
|
||||
- **Status**: Disabled by default
|
||||
|
||||
## Environment Variables
|
||||
```bash
|
||||
FARTCOIN_ENABLED=false # Enable/disable FARTCOIN trading
|
||||
FARTCOIN_POSITION_SIZE=20 # 20% of portfolio (not fixed USD)
|
||||
FARTCOIN_LEVERAGE=10 # Max 10x leverage
|
||||
FARTCOIN_USE_PERCENTAGE_SIZE=true # Always true for FARTCOIN
|
||||
```
|
||||
|
||||
## Enabling FARTCOIN Trading
|
||||
|
||||
### Via Settings UI (Recommended)
|
||||
1. Navigate to Settings page: `http://localhost:3001/settings`
|
||||
2. Scroll to "🎈 Fartcoin (FARTCOIN-PERP)" section
|
||||
3. Toggle "Enable Fartcoin Trading" to ON
|
||||
4. Adjust position size percentage (recommended: 10-20%)
|
||||
5. Set leverage (recommended: 10x for max profit potential)
|
||||
6. Click "Save Settings"
|
||||
|
||||
### Via Environment Variables
|
||||
1. Edit `.env` file
|
||||
2. Set `FARTCOIN_ENABLED=true`
|
||||
3. Adjust `FARTCOIN_POSITION_SIZE` (1-100%)
|
||||
4. Adjust `FARTCOIN_LEVERAGE` (1-10x)
|
||||
5. Restart container: `docker restart trading-bot-v4`
|
||||
|
||||
### Via TradingView Alert
|
||||
Ensure your TradingView alert includes FARTCOIN symbol:
|
||||
```json
|
||||
{
|
||||
"symbol": "FARTCOINUSDT", // or "FARTCOIN"
|
||||
"direction": "long",
|
||||
// ... other fields
|
||||
}
|
||||
```
|
||||
|
||||
The bot will automatically normalize `FARTCOINUSDT` to `FARTCOIN-PERP`.
|
||||
|
||||
## Position Size Calculation
|
||||
|
||||
**Percentage-based sizing formula:**
|
||||
```
|
||||
Base Capital = Portfolio × Position Size %
|
||||
Notional Position = Base Capital × Leverage
|
||||
|
||||
Example with $1000 portfolio:
|
||||
- Position Size: 20% → Base = $200
|
||||
- Leverage: 10x → Notional = $2000
|
||||
- Risk Exposure: $200 (max loss is your base capital)
|
||||
```
|
||||
|
||||
**Risk/Reward Example:**
|
||||
- Portfolio: $1000
|
||||
- Position: 20% ($200) × 10x = $2000 notional
|
||||
- Max Loss (1.5% SL): $30 (1.5% of $2000)
|
||||
- Target Win (1.8% TP): $36 (1.8% of $2000)
|
||||
- R:R Ratio: 1:1.2
|
||||
|
||||
## Key Differences from SOL/ETH
|
||||
|
||||
| Feature | FARTCOIN | SOL | ETH |
|
||||
|---------|----------|-----|-----|
|
||||
| **Position Sizing** | Percentage-based | Fixed USD | Fixed USD |
|
||||
| **Default Enabled** | ❌ Disabled | ✅ Enabled | ✅ Enabled |
|
||||
| **Purpose** | Profit generation | Profit generation | Data collection |
|
||||
| **Default Size** | 20% portfolio | $210 fixed | $4 fixed |
|
||||
| **Default Leverage** | 10x | 10x | 1x |
|
||||
| **Max Leverage** | 10x | 20x | 20x |
|
||||
|
||||
## Risk Management
|
||||
|
||||
**Important Notes:**
|
||||
1. **Disabled by default** - Safe to deploy, enable when ready
|
||||
2. **Max 10x leverage** - Based on Drift Protocol margin requirements
|
||||
3. **Percentage sizing** - Automatically scales with portfolio size
|
||||
4. **Quality thresholds** - Uses same signal quality filters as SOL/ETH
|
||||
5. **Adaptive leverage** - Quality score determines actual leverage used
|
||||
|
||||
## TradingView Setup
|
||||
|
||||
Your indicator should include FARTCOIN detection logic. The bot will:
|
||||
1. Receive webhook with `"symbol": "FARTCOINUSDT"`
|
||||
2. Normalize to `FARTCOIN-PERP` via `normalizeTradingViewSymbol()`
|
||||
3. Check if `FARTCOIN_ENABLED=true`
|
||||
4. Calculate position size as percentage of free collateral
|
||||
5. Apply max 10x leverage
|
||||
6. Execute trade on Drift Protocol market index 22
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
Before enabling FARTCOIN trading in production:
|
||||
- [ ] Settings UI shows FARTCOIN section correctly
|
||||
- [ ] Toggle switch works (enabled/disabled state)
|
||||
- [ ] Position size slider adjusts (1-100%)
|
||||
- [ ] Leverage slider adjusts (1-10x)
|
||||
- [ ] Risk calculator shows correct values
|
||||
- [ ] Percentage calculation: 20% of $1000 = $200 base
|
||||
- [ ] Notional calculation: $200 × 10x = $2000
|
||||
- [ ] Settings save successfully to .env
|
||||
- [ ] Container restart applies new settings
|
||||
- [ ] Symbol detection works: "FARTCOINUSDT" → "FARTCOIN-PERP"
|
||||
- [ ] Test trade executes with correct position size
|
||||
|
||||
## Monitoring
|
||||
|
||||
Watch for these log messages when FARTCOIN trading is active:
|
||||
```
|
||||
📊 Percentage sizing: 20% of $1000.00 = $200.00
|
||||
📊 Adaptive leverage: Quality 92 → 10x leverage
|
||||
🎯 Opening position: FARTCOIN-PERP LONG $2000.00 (10x leverage)
|
||||
✅ Position opened successfully
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**FARTCOIN trades not executing:**
|
||||
1. Check `FARTCOIN_ENABLED=true` in settings
|
||||
2. Verify symbol normalization in logs
|
||||
3. Check quality score meets threshold (90+ for LONG, 95+ for SHORT)
|
||||
4. Ensure TradingView alert includes correct symbol
|
||||
5. Verify free collateral > required amount
|
||||
|
||||
**Position size incorrect:**
|
||||
1. Check `FARTCOIN_USE_PERCENTAGE_SIZE=true` (should always be true)
|
||||
2. Verify percentage calculation in logs
|
||||
3. Check free collateral value
|
||||
4. Ensure leverage is between 1-10x
|
||||
|
||||
**Settings not saving:**
|
||||
1. Check .env file permissions (should be writable)
|
||||
2. Verify container has access to .env file
|
||||
3. Check logs for "Settings updated" message
|
||||
4. Restart container after manual .env changes
|
||||
Reference in New Issue
Block a user