feat: Add FARTCOIN-PERP market support with percentage-based sizing

- Added FARTCOIN-PERP to SUPPORTED_MARKETS (market index 22)
- Updated TradingConfig interface with fartcoin symbol settings
- Added default config: 20% portfolio, 10x leverage, disabled by default
- Updated normalizeTradingViewSymbol to detect FARTCOIN
- Enhanced getPositionSizeForSymbol for FARTCOIN-PERP handling
- Enhanced getActualPositionSizeForSymbol for percentage-based sizing
- Added FARTCOIN ENV variable loading in getConfigFromEnv
- Updated Settings UI with FARTCOIN section and percentage badge
- Added FARTCOIN fields to settings API endpoints (GET/POST)
- Created comprehensive documentation in docs/markets/FARTCOIN-PERP.md
- Build successful: TypeScript compilation and static generation complete

Co-authored-by: mindesbunister <32161838+mindesbunister@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-12-06 17:44:19 +00:00
parent d3b83ae95a
commit 2df6c69b92
4 changed files with 274 additions and 0 deletions

View File

@@ -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(),

View File

@@ -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">