ranger-finance

Par elophanto · elophanto

SDK Ranger Finance pour créer des applications de trading de contrats à terme perpétuels sur Solana. Premier agrégateur de Perps sur Solana — agrège la liquidité sur plusieurs protocoles de perps (Drift, Flash, Adrena, Jupiter). À utiliser pour intégrer le trading de perps, le routage intelligent des ordres, la gestion de positions ou la création d'agents de trading IA.

npx skills add https://github.com/elophanto/elophanto --skill ranger-finance

Guide de développement du SDK Ranger Finance

Un guide complet pour construire des applications Solana avec Ranger Finance - le premier agrégateur de contrats perpétuels sur Solana.

Vue d'ensemble

Ranger Finance est un Smart Order Router (SOR) qui agrège les échanges de contrats perpétuels sur plusieurs protocoles Solana :

  • Drift Protocol : Principal DEX de contrats perpétuels sur Solana
  • Flash Trade : Contrats perpétuels haute performance
  • Adrena : Protocole de trading avec effet de levier
  • Jupiter Perps : Plateforme de contrats perpétuels de Jupiter

Avantages clés

  • Meilleure exécution : Route automatiquement les ordres vers les venues avec les meilleurs prix
  • API unifiée : Interface unique pour tous les protocoles de contrats perpétuels supportés
  • Agrégation de positions : Visualisez et gérez les positions sur tous les venues
  • Support des agents IA : Serveur MCP intégré pour les agents de trading IA

Démarrage rapide

Installation (TypeScript)

# Clonez la démo du SDK
git clone https://github.com/ranger-finance/sor-ts-demo.git
cd sor-ts-demo
npm install

Configuration de l'environnement

Créez un fichier .env :

RANGER_API_KEY=your_api_key_here
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
WALLET_PRIVATE_KEY=your_base58_private_key  # Optionnel, pour signer

Configuration de base

import { SorApi, TradeSide } from 'ranger-sor-sdk';
import dotenv from 'dotenv';

dotenv.config();

// Initialisez le client API SOR
const sorApi = new SorApi({
  apiKey: process.env.RANGER_API_KEY!,
  solanaRpcUrl: process.env.SOLANA_RPC_URL,
});

// Votre clé publique de portefeuille
const walletAddress = 'YOUR_WALLET_PUBLIC_KEY';

Concepts principaux

1. Côtés de trading

type TradeSide = 'Long' | 'Short';

2. Types d'ajustement

type AdjustmentType =
  | 'Quote'           // Obtenir une cotation uniquement
  | 'Increase'        // Ouvrir ou augmenter une position
  | 'DecreaseFlash'   // Diminuer via Flash
  | 'DecreaseJupiter' // Diminuer via Jupiter
  | 'DecreaseDrift'   // Diminuer via Drift
  | 'DecreaseAdrena'  // Diminuer via Adrena
  | 'CloseFlash'      // Fermer via Flash
  | 'CloseJupiter'    // Fermer via Jupiter
  | 'CloseDrift'      // Fermer via Drift
  | 'CloseAdrena'     // Fermer via Adrena
  | 'CloseAll';       // Fermer la position entière

3. Interface Position

interface Position {
  id: string;
  symbol: string;
  side: TradeSide;
  quantity: number;
  entry_price: number;
  liquidation_price: number;
  position_leverage: number;
  real_collateral: number;
  unrealized_pnl: number;
  borrow_fee: number;
  funding_fee: number;
  open_fee: number;
  close_fee: number;
  created_at: string;
  opened_at: string;
  platform: string;  // 'DRIFT', 'FLASH', 'ADRENA', 'JUPITER'
}

4. Réponse de cotation

interface Quote {
  base: number;
  fee: number;
  total: number;
  fee_breakdown: {
    base_fee: number;
    spread_fee: number;
    volatility_fee: number;
    margin_fee: number;
    close_fee: number;
    other_fees: number;
  };
}

interface VenueAllocation {
  venue_name: string;
  collateral: number;
  size: number;
  quote: Quote;
  order_available_liquidity: number;
  venue_available_liquidity: number;
}

interface OrderMetadataResponse {
  venues: VenueAllocation[];
  total_collateral: number;
  total_size: number;
}

Opérations de trading

Obtenir une cotation

Avant d'exécuter un trade, obtenez une cotation pour voir les prix entre les venues :

import { SorApi, OrderMetadataRequest, TradeSide } from 'ranger-sor-sdk';

const sorApi = new SorApi({ apiKey: process.env.RANGER_API_KEY! });

async function getQuote() {
  const request: OrderMetadataRequest = {
    fee_payer: walletAddress,
    symbol: 'SOL',
    side: 'Long' as TradeSide,
    size: 1.0,                        // Taille de position 1 SOL
    collateral: 10.0,                 // Collatéral 10 USDC (effet de levier 10x)
    size_denomination: 'SOL',
    collateral_denomination: 'USDC',
    adjustment_type: 'Quote',
  };

  const quote = await sorApi.getOrderMetadata(request);

  console.log('Venues disponibles :');
  quote.venues.forEach(venue => {
    console.log(`  ${venue.venue_name}: ${venue.quote.total} USDC`);
  });

  return quote;
}

Ouvrir/Augmenter une position

async function openLongPosition() {
  const request = {
    fee_payer: walletAddress,
    symbol: 'SOL',
    side: 'Long' as TradeSide,
    size: 1.0,
    collateral: 10.0,
    size_denomination: 'SOL',
    collateral_denomination: 'USDC',
    adjustment_type: 'Increase' as const,
  };

  // Obtenez les instructions de transaction
  const response = await sorApi.increasePosition(request);

  console.log('Message de transaction (base64) :', response.message);

  if (response.meta) {
    console.log('Prix exécuté :', response.meta.executed_price);
    console.log('Venues utilisées :', response.meta.venues_used);
  }

  return response;
}

// Ouvrir une position courte
async function openShortPosition() {
  const request = {
    fee_payer: walletAddress,
    symbol: 'ETH',
    side: 'Short' as TradeSide,
    size: 0.5,
    collateral: 100.0,
    size_denomination: 'ETH',
    collateral_denomination: 'USDC',
    adjustment_type: 'Increase' as const,
  };

  return await sorApi.increasePosition(request);
}

Diminuer une position

async function decreasePosition() {
  const request = {
    fee_payer: walletAddress,
    symbol: 'SOL',
    side: 'Long' as TradeSide,
    size: 0.5,                        // Diminuer de 0,5 SOL
    collateral: 5.0,                  // Retirer 5 USDC de collatéral
    size_denomination: 'SOL',
    collateral_denomination: 'USDC',
    adjustment_type: 'DecreaseFlash' as const,  // Router via Flash
  };

  return await sorApi.decreasePosition(request);
}

Fermer une position

// Fermer la position entière sur un venue spécifique
async function closePosition() {
  const request = {
    fee_payer: walletAddress,
    symbol: 'SOL',
    side: 'Long' as TradeSide,
    adjustment_type: 'CloseFlash' as const,
  };

  return await sorApi.closePosition(request);
}

// Fermer toutes les positions sur tous les venues
async function closeAllPositions() {
  const request = {
    fee_payer: walletAddress,
    symbol: 'SOL',
    side: 'Long' as TradeSide,
    adjustment_type: 'CloseAll' as const,
  };

  return await sorApi.closePosition(request);
}

Signer et exécuter une transaction

import { Keypair, VersionedTransaction } from '@solana/web3.js';
import bs58 from 'bs58';

async function executeTradeWithSigning() {
  // Obtenez les instructions de transaction
  const txResponse = await sorApi.increasePosition({
    fee_payer: walletAddress,
    symbol: 'SOL',
    side: 'Long',
    size: 1.0,
    collateral: 10.0,
    size_denomination: 'SOL',
    collateral_denomination: 'USDC',
    adjustment_type: 'Increase',
  });

  // Créez une paire de clés à partir de la clé privée
  const privateKeyBytes = bs58.decode(process.env.WALLET_PRIVATE_KEY!);
  const keypair = Keypair.fromSecretKey(privateKeyBytes);

  // Définissez la fonction de signature
  const signTransaction = async (tx: VersionedTransaction) => {
    tx.sign([keypair]);
    return tx;
  };

  // Exécutez la transaction
  const result = await sorApi.executeTransaction(txResponse, signTransaction);

  console.log('Signature de la transaction :', result.signature);
  return result;
}

Gestion des positions

Récupérer toutes les positions

async function getAllPositions() {
  const positions = await sorApi.getPositions(walletAddress);

  positions.positions.forEach(pos => {
    console.log(`${pos.symbol} ${pos.side}: ${pos.quantity} @ ${pos.entry_price}`);
    console.log(`  Plateforme : ${pos.platform}`);
    console.log(`  PnL : ${pos.unrealized_pnl}`);
    console.log(`  Liquidation : ${pos.liquidation_price}`);
  });

  return positions;
}

Filtrer les positions par plateforme

async function getDriftPositions() {
  const positions = await sorApi.getPositions(walletAddress, {
    platforms: ['DRIFT'],
  });

  return positions;
}

async function getFlashAndAdrenaPositions() {
  const positions = await sorApi.getPositions(walletAddress, {
    platforms: ['FLASH', 'ADRENA'],
  });

  return positions;
}

Filtrer les positions par symbole

async function getSolPositions() {
  const positions = await sorApi.getPositions(walletAddress, {
    symbols: ['SOL-PERP'],
  });

  return positions;
}

Intégration avec les agents IA

Ranger fournit un serveur MCP (Model Context Protocol) pour l'intégration avec les agents IA.

Installation (Python)

pip install mcp-agent numpy

Outils du serveur MCP

Le serveur MCP de Ranger expose ces outils :

Outils SOR :

  • sor_get_trade_quote - Obtenir des cotations de prix
  • sor_increase_position - Ouvrir/augmenter des positions
  • sor_decrease_position - Réduire des positions
  • sor_close_position - Fermer des positions

Outils API de données :

  • data_get_positions - Récupérer les positions actuelles
  • data_get_trade_history - Historique de trading
  • data_get_liquidations - Données de liquidation et signaux
  • data_get_funding_rates - Analyse des taux de financement

Exemple : Agent de réversion à la moyenne

import asyncio
from ranger_mcp_agent.examples.mean_reversion_agent import run_mean_reversion_agent

async def main():
    # Exécutez une stratégie de trading de réversion à la moyenne
    await run_mean_reversion_agent()

if __name__ == "__main__":
    asyncio.run(main())

Démarrer le serveur MCP

cd ranger-agent-kit/perps-mcp
cp .env.example .env
# Modifiez .env avec vos identifiants API
python -m ranger_mcp

Référence API

Classe SorApi

class SorApi {
  constructor(config: SorSdkConfig);

  // Obtenir une cotation pour un trade
  getOrderMetadata(request: OrderMetadataRequest): Promise<OrderMetadataResponse>;

  // Ouvrir ou augmenter une position
  increasePosition(request: IncreasePositionRequest): Promise<TransactionResponse>;

  // Réduire une position
  decreasePosition(request: DecreasePositionRequest): Promise<TransactionResponse>;

  // Fermer une position
  closePosition(request: ClosePositionRequest): Promise<TransactionResponse>;

  // Obtenir les positions d'un portefeuille
  getPositions(
    publicKey: string,
    options?: {
      platforms?: string[];
      symbols?: string[];
      startDate?: string;
      endDate?: string;
    }
  ): Promise<PositionsResponse>;

  // Exécuter une transaction signée
  executeTransaction(
    transactionResponse: TransactionResponse,
    signTransaction: (tx: VersionedTransaction) => Promise<VersionedTransaction>
  ): Promise<{ signature: string }>;

  // Obtenir la connexion Solana
  getConnection(): Connection;
}

Configuration

interface SorSdkConfig {
  apiKey: string;
  sorApiBaseUrl?: string;   // Par défaut : API SOR de Ranger
  dataApiBaseUrl?: string;  // Par défaut : API de données de Ranger
  solanaRpcUrl?: string;    // Par défaut : RPC Mainnet
}

Types de requête

interface BaseRequest {
  fee_payer: string;
  symbol: string;
  side: TradeSide;
  size_denomination?: string;
  collateral_denomination?: string;
}

interface IncreasePositionRequest extends BaseRequest {
  size: number;
  collateral: number;
  size_denomination: string;
  collateral_denomination: string;
  adjustment_type: 'Increase';
}

interface DecreasePositionRequest extends BaseRequest {
  size: number;
  collateral: number;
  size_denomination: string;
  collateral_denomination: string;
  adjustment_type: 'DecreaseFlash' | 'DecreaseJupiter' | 'DecreaseDrift' | 'DecreaseAdrena';
}

interface ClosePositionRequest extends BaseRequest {
  adjustment_type: 'CloseFlash' | 'CloseJupiter' | 'CloseDrift' | 'CloseAdrena' | 'CloseAll';
}

Types de réponse

interface TransactionResponse {
  message: string;  // Transaction encodée en base64
  meta?: {
    executed_price?: number;
    executed_size?: number;
    executed_collateral?: number;
    venues_used?: string[];
  };
}

interface PositionsResponse {
  positions: Position[];
}

Marchés supportés

Ranger agrège les marchés de contrats perpétuels sur :

Protocole Marchés
Drift SOL, BTC, ETH et 20+ actifs
Flash SOL, BTC, ETH
Adrena SOL, BTC, ETH
Jupiter SOL, BTC, ETH

Gestion des erreurs

try {
  const response = await sorApi.increasePosition(request);
} catch (error) {
  if (error.error_code) {
    // Erreur API
    console.error('Erreur API :', error.message);
    console.error('Code d\'erreur :', error.error_code);
  } else {
    // Erreur de réseau ou autre
    throw error;
  }
}

Bonnes pratiques

  1. Toujours obtenir les cotations en premier : Avant d'exécuter des trades, utilisez getOrderMetadata pour comparer les prix entre les venues.

  2. Gérer la signature de transactions de manière sécurisée : Ne codez jamais en dur les clés privées. Utilisez des variables d'environnement ou une gestion sécurisée des clés.

  3. Surveiller les positions : Récupérez régulièrement les positions pour suivre le PnL et les prix de liquidation.

  4. Utiliser le venue approprié : Lors de la diminution/fermeture, choisissez le venue où votre position existe.

  5. Définir un collatéral approprié : Considérez l'effet de levier lors de la définition du collatéral. Un collatéral plus élevé = risque de liquidation plus faible.

Ressources

Structure de compétence

ranger-finance/
├── SKILL.md                           # Ce fichier
├── resources/
│   ├── api-reference.md               # Référence des endpoints API
│   └── types-reference.md             # Types TypeScript complets
├── examples/
│   ├── basic/
│   │   └── example.ts                 # Opérations de trading basiques
│   ├── positions/
│   │   └── example.ts                 # Requêtes et gestion des positions
│   └── transactions/
│       └── example.ts                 # Flux de signature de transaction
├── templates/
│   └── setup.ts                       # Modèle de configuration prêt à l'emploi
└── docs/
    ├── troubleshooting.md             # Problèmes courants et solutions
    └── ai-agent-integration.md        # Guide de configuration des agents IA

Vérification

  • Un appel RPC/SDK réel a été effectué (mainnet, devnet ou validateur local) et la charge utile de réponse est capturée dans la transcription, non pas simplement paraphrasée
  • Chaque transaction a été simulée (simulateTransaction ou équivalent) avant toute étape de signature/envoi ; les journaux de simulation sont joints
  • Pour toute transaction signée/envoyée, la signature résultante est enregistrée et confirmée sur la chaîne (statut retourné par getSignatureStatuses ou URL d'explorateur)
  • Le slippage, les frais de priorité et les limites d'unités de calcul ont été définis explicitement avec des valeurs numériques concrètes, non laissés aux défauts de bibliothèque
  • Les adresses de compte, les mints et les ID de programme utilisés dans la exécution correspondent aux adresses ranger-perps documentées pour le cluster ciblé (pas de mélange mainnet/devnet)
  • Le chemin d'échec a été exercé au moins une fois (solde insuffisant, oracle périmé, blockhash expiré, etc.) et la gestion des erreurs de l'agent a produit un message lisible par l'homme

Skills similaires