Type/to search
8
Follow
1365
Followers
古代戦略のゼロ手数料再開:FMZ + 軽量DEX + AIの実践
Discussions
Created 2026-01-22 09:30:47  Updated 2026-01-22 18:12:51
 9
 977

img

序文

最近、FMZ定量プラットフォームが正式に統合されました。Lighter DEX正直なところ、このニュースを初めて見たときはあまり注目していませんでした。市場にはDEXが無数に存在しているからです。しかし、詳しく調べてみると、ある特徴が目に留まりました。それは、取引手数料がゼロであることです。

はい、その通りです。Lighter DEXは一般トレーダーに手数料ゼロを提供しています。これを見てすぐに思い出しました。手数料のせいで何年も前に「棚上げ」にしていた戦略を、ついに復活させられるだろうか?そう思って、FMZを開設したのです…戦略スクエアそんな「古代」からの戦略を探して…

1. Lighter

この新しく追加されたDEXについてはあまり詳しく説明しません。興味のある方は、情報を調べてみてください。現在、ユーザーエクスペリエンスは非常に良好です。ユーザーエクスペリエンスの面では、Lighterは分散型の透明性を維持しながら、中央集権型取引所に匹敵するパフォーマンスを提供し、高頻度のAPIアクセスでも比較的安定しています。

データ概要

以下にいくつかの情報をまとめます。

配置する

次に、FMZの設定方法について簡単に紹介します。LighterFMZ プラットフォームの交換ページに Lighter API KEY 構成情報を追加します。

img

次の 3 つの項目を設定する必要があります。

  • 署名API秘密鍵
    これはウォレットの秘密鍵ではありません。この署名用秘密鍵は、注文や取引を行う際に使用する秘密鍵で、Lighterにログインし、https://app.lighter.xyz でウォレットを接続した後に作成されます。

    img

    • Lighter テスト環境にログインしている場合、作成されるキーはテスト環境キーになりますが、ここでは詳しく説明しません。
    • 署名用秘密鍵を作成する際は、インデックスを指定する必要があります。0~2は予約ビットで、3以降が指定可能です。
    • これらのログインと作成の手順にはすべてウォレットの署名が必要ですが、私は Binance Wallet を使用して良い経験をしました。

    作成された署名秘密鍵設定は、FMZ の Exchange 追加ページの対応するコントロール編集ボックスで行うことができます。

  • 重要な注意:
    Lighter 先物契約取引所をサポートするには、カストディアン プログラムの最新バージョンをダウンロードする必要があります。

  • APIインデックス
    署名秘密鍵に対応するインデックスを入力します。

  • アカウントインデックス
    アカウント インデックスは Lighter の API を通じて取得できます。

    • APIインターフェース:https://mainnet.zklighter.elliot.ai/api/v1/account?by=l1_address&value={钱包地址}
      たとえば、ブラウザで直接アドレスにアクセスします。https://mainnet.zklighter.elliot.ai/api/v1/account?by=l1_address&value=0x123xxxx0x123xxxxこれは単なるアドレスの例です。実際に使用するときはこの内容を置き換えてください。
      返されるデータ:

      json
      { "code": 200, "total": 1, "accounts": [ { "code": 0, "account_type": 0, "index": 1234567, "l1_address": "0x123xxxx",

      "index": 1234567それがあなたのアカウントインデックスです。

    • 初期作成プロセスは、資産 (USDC など) が転送されたときにのみ開始されます。Lighterアカウント

    • メインネット エンドポイントを使用して取得されたインターフェースはメインネット アカウント インデックスを取得しますが、テストネット エンドポイントを使用して取得されたインターフェースはテストネット アカウント インデックスを取得することに注意してください。

    なぜこのアカウントインデックスを入力する必要があるのでしょうか?Lighterサブアカウントシステムでは、アカウントインデックスに基づいて異なるアカウントを区別します。サブアカウントを使用する必要がある場合は、ここでサブアカウントのアカウントインデックスを設定できます(サブアカウントのアカウントインデックスは、上記のクエリリンクによって返されるJSONデータに表示されます)。

2. FMZにおける古代の戦略

手数料ゼロ:ゲームチェンジャー

これが私が一番興奮する機能です。Lighterは一般トレーダー向けに手数料無料ポリシーを提供しています。

  • 取引手数料ゼロとはどういう意味ですか?

    高頻度取引戦略では、取引手数料によって利益が「食いつぶされる」ことがなくなりました。
    メッシュ戦略により、より密なメッシュ間隔を設定できます。
    裁定取引戦略の損益分岐点が大幅に削減されました。
    「理論的には実行可能だが、実際には取引手数料によって打ち負かされる」戦略が、ついに使用される場所を見つけた。

古代の戦略を発掘する:ゼロ取引手数料の魅力

戦略図書館考古学

「取引手数料ゼロで復活できる戦略は何か?」という疑問を念頭に、FMZの戦略ライブラリとコミュニティを検索し始めました。するとすぐに、馴染みのある戦略が目に留まりました。

https://www.fmz.com/digest-topic/1211

この戦略はシンプルで分かりやすいですが、取引手数料がかかる環境ではほぼ確実に損失につながります。しかし、Lighterの取引手数料ゼロの環境では、試してみる価値があります。

それで、質問です:

問題はここにあります。コードが古すぎるのです。戦略を見てみると、コードは単純で力ずくで、UIコンテンツはほとんどなく、アクセシビリティ機能もいくつか欠けています。何が欠けているかの例をいくつか挙げてみましょう。

  • 一部の API インターフェースは古くなっています。
  • 最新のリスク管理モジュールが欠けています。
  • 情報が不足しています。
  • 収益統計がありません。

このコードを手動でリファクタリングする?正直言って、ちょっと気が重い。でも、AIにリファクタリングを任せるという「手軽な」解決策を思いついた。

3. 再編戦略

まず、安全策を講じましょう。この記事は、新興のDEX取引所におけるAIを用いた戦略の再構築を試みる試みに過ぎず、再構築された戦略の収益性を保証するものではありません。そこで、Claudeを使ってこの古来の戦略を再構築してみましょう。コードを一から書き直すつもりはありません。私の要件は次のとおりです。

  • 元の戦略の核となるロジックを維持する
  • FMZの最新API仕様に適合
  • 必要なリスク管理およびログモジュールを追加する
  • 比較的完全かつ明確な情報が表示されています。
  • コードロジックを適切に最適化する

元のコードをAIに渡す

元の戦略コードをコピーし、要件とともにAIに送信しました。数回の対話と調整を経て、AIはリファクタリングされたコードを生成してくれました。

AIと会話する内容は投稿しませんが、基本的にはリクエストを出して、テストして、満足できなかったらさらにリクエストを出すという内容です。
以下の場合にも使用できます:
bash: while :; do cat PROMPT.md | claude-code ; done
: )
(学ぶべき考え)

javascript
/* 高频做市策略 - FMZ期货版(带仓位矫正) 策略参数: - sleeptime: 休眠时间(毫秒) - 默认3500 - floatamountbuy: 买单深度阈值 - 默认20 - floatamountsell: 卖单深度阈值 - 默认20 - diffprice: 最小套利差价 - 默认50 - baseAmount: 基础下单量 - 默认0.1 - maxPosition: 最大单边持仓量 - 默认10 - stopLossRatio: 止损比例 - 默认0.9 (90%) - closeOnExit: 退出时清仓 - 默认false */ // 全局变量 var pricePrecision = 2; var amountPrecision = 3; var tickSize = 0.01; var minQty = 0.001; var symbol = "ETH_USDT.swap"; // 统计信息 var stats = { startTime: 0, cycleCount: 0, orderCount: 0, cancelCount: 0, initialEquity: 0, currentEquity: 0, maxEquity: 0, maxDrawdown: 0, isStopLoss: false, lastLogCleanTime: 0, lastEmergencyTime: 0 }; // 日志清理配置 var LOG_CLEAN_INTERVAL = 60 * 60 * 1000; var LOG_RESERVE_COUNT = 10000; var EMERGENCY_COOLDOWN = 5000; // ==================== 精度工具函数 ==================== /** * 从数值推断精度(小数位数) * 例如: 0.005 -> 3, 0.0001 -> 4, 0.1 -> 1, 1 -> 0 */ function GetPrecisionFromValue(value) { if (!value || value >= 1) return 0; var str = value.toString(); // 处理科学计数法 (如 1e-4) if (str.indexOf('e') !== -1) { var match = str.match(/e-(\d+)/); return match ? parseInt(match[1]) : 0; } // 处理普通小数 if (str.indexOf('.') === -1) return 0; return str.split('.')[1].length; } /** * 规范化下单量 * 1. 按精度取整 * 2. 确保是 minQty 的整数倍 * 3. 不小于 minQty */ function NormalizeAmount(amount) { if (amount <= 0) return 0; // 按精度取整 var normalized = _N(amount, amountPrecision); // 确保是 minQty 的整数倍 if (minQty > 0) { normalized = Math.floor(normalized / minQty) * minQty; normalized = _N(normalized, amountPrecision); } // 检查最小下单量 if (normalized < minQty) { return 0; } return normalized; } /** * 规范化价格 */ function NormalizePrice(price) { if (tickSize > 0) { price = Math.round(price / tickSize) * tickSize; } return _N(price, pricePrecision); } // 取消全部订单 function CancelPendingOrders() { var orders = _C(exchange.GetOrders, symbol); var count = 0; for (var j = 0; j < orders.length; j++) { exchange.CancelOrder(orders[j].Id, orders[j]); count++; } if (count > 0) { stats.cancelCount += count; } return count; } // 计算将要下单的价格 function GetPrice(Type, depth) { var amountBids = 0; var amountAsks = 0; if (Type == "Buy") { for (var i = 0; i < 20 && i < depth.Bids.length; i++) { amountBids += depth.Bids[i].Amount; if (amountBids > floatamountbuy) { return NormalizePrice(depth.Bids[i].Price + tickSize); } } } if (Type == "Sell") { for (var j = 0; j < 20 && j < depth.Asks.length; j++) { amountAsks += depth.Asks[j].Amount; if (amountAsks > floatamountsell) { return NormalizePrice(depth.Asks[j].Price - tickSize); } } } return NormalizePrice(depth.Asks[0].Price); } // 获取持仓信息 function GetPosition() { var positions = _C(exchange.GetPositions, symbol); var pos = { long: { amount: 0, price: 0, profit: 0 }, short: { amount: 0, price: 0, profit: 0 } }; for (var i = 0; i < positions.length; i++) { var p = positions[i]; if (p.Type === PD_LONG || p.Type === 0) { pos.long.amount = p.Amount; pos.long.price = p.Price; pos.long.profit = p.Profit || 0; } else { pos.short.amount = p.Amount; pos.short.price = p.Price; pos.short.profit = p.Profit || 0; } } return pos; } // 计算账户权益 function GetEquity(account, pos) { var equity = account.Balance + account.FrozenBalance + pos.long.profit + pos.short.profit; return equity; } // 检查资金是否足够下单 function CheckFunds(account, price, amount, leverage) { leverage = leverage || 10; var requiredMargin = (price * amount) / leverage; var availableBalance = account.Balance; var safeBalance = availableBalance * 0.9; return safeBalance >= requiredMargin; } // ==================== 仓位矫正机制 ==================== /** * 计算动态开仓量(负反馈机制) */ function CalcOpenAmount(pos, direction) { var currentPos = (direction === "long") ? pos.long.amount : pos.short.amount; var posRatio = currentPos / maxPosition; if (currentPos >= maxPosition) { return 0; } var amount = baseAmount; if (posRatio > 0.8) { amount = baseAmount * 0.2; } else if (posRatio > 0.6) { amount = baseAmount * 0.4; } else if (posRatio > 0.4) { amount = baseAmount * 0.6; } else if (posRatio > 0.2) { amount = baseAmount * 0.8; } var netPos = pos.long.amount - pos.short.amount; if (direction === "long" && netPos > maxPosition * 0.3) { amount = amount * 0.5; } else if (direction === "short" && netPos < -maxPosition * 0.3) { amount = amount * 0.5; } return NormalizeAmount(amount); } /** * 计算动态平仓量 */ function CalcCloseAmount(pos, direction) { var currentPos = (direction === "long") ? pos.long.amount : pos.short.amount; if (currentPos <= 0) return 0; var posRatio = currentPos / maxPosition; var amount = baseAmount; if (posRatio > 1.0) { amount = currentPos; } else if (posRatio > 0.8) { amount = baseAmount * 3.0; } else if (posRatio > 0.6) { amount = baseAmount * 2.0; } else if (posRatio > 0.4) { amount = baseAmount * 1.5; } amount = Math.min(amount, currentPos); return NormalizeAmount(amount); } /** * 计算平仓价格(仓位重时更激进) */ function CalcClosePrice(pos, depth, direction) { var currentPos = (direction === "long") ? pos.long.amount : pos.short.amount; var posRatio = currentPos / maxPosition; if (direction === "long") { if (posRatio > 1.0) { return NormalizePrice(depth.Bids[0].Price - tickSize * 3); } else if (posRatio > 0.8) { return NormalizePrice(depth.Bids[0].Price); } else if (posRatio > 0.5) { var midPrice = (depth.Bids[0].Price + depth.Asks[0].Price) / 2; return NormalizePrice(midPrice); } return NormalizePrice(depth.Asks[0].Price - tickSize); } else { if (posRatio > 1.0) { return NormalizePrice(depth.Asks[0].Price + tickSize * 3); } else if (posRatio > 0.8) { return NormalizePrice(depth.Asks[0].Price); } else if (posRatio > 0.5) { var midPrice = (depth.Bids[0].Price + depth.Asks[0].Price) / 2; return NormalizePrice(midPrice); } return NormalizePrice(depth.Bids[0].Price + tickSize); } } /** * 紧急减仓 */ function EmergencyReduce(pos, depth) { var now = new Date().getTime(); if (now - stats.lastEmergencyTime < EMERGENCY_COOLDOWN) { return false; } var needReduce = false; if (pos.long.amount > maxPosition * 1.2) { var reduceAmount = NormalizeAmount(pos.long.amount - maxPosition); if (reduceAmount > 0) { Log("⚠️ 多头严重超标 (" + pos.long.amount + "/" + maxPosition + "),市价减仓: " + reduceAmount, "#FF0000"); var orderId = exchange.CreateOrder(symbol, "closebuy", -1, reduceAmount); if (orderId) { stats.orderCount++; stats.lastEmergencyTime = now; } needReduce = true; } } if (pos.short.amount > maxPosition * 1.2) { var reduceAmount = NormalizeAmount(pos.short.amount - maxPosition); if (reduceAmount > 0) { Log("⚠️ 空头严重超标 (" + pos.short.amount + "/" + maxPosition + "),市价减仓: " + reduceAmount, "#FF0000"); var orderId = exchange.CreateOrder(symbol, "closesell", -1, reduceAmount); if (orderId) { stats.orderCount++; stats.lastEmergencyTime = now; } needReduce = true; } } if (needReduce) { Sleep(1000); } return needReduce; } function IsPositionOverload(pos) { return pos.long.amount > maxPosition || pos.short.amount > maxPosition; } // ==================== 日志清理 ==================== function CleanLogs() { var now = new Date().getTime(); if (now - stats.lastLogCleanTime > LOG_CLEAN_INTERVAL) { LogReset(LOG_RESERVE_COUNT); stats.lastLogCleanTime = now; Log("日志已清理,保留最近 " + LOG_RESERVE_COUNT + " 条", "#0000FF"); } } // ==================== 清仓相关 ==================== function CloseAllPositions(reason) { reason = reason || "手动触发"; Log("========== 触发清仓 [" + reason + "] ==========", "#FF0000"); CancelPendingOrders(); Sleep(500); var pos = GetPosition(); if (pos.long.amount > 0) { var orderId = exchange.CreateOrder(symbol, "closebuy", -1, pos.long.amount); if (orderId) { Log("市价平多: " + pos.long.amount, "#FF0000"); } } if (pos.short.amount > 0) { var orderId = exchange.CreateOrder(symbol, "closesell", -1, pos.short.amount); if (orderId) { Log("市价平空: " + pos.short.amount, "#FF0000"); } } Sleep(2000); var finalPos = GetPosition(); if (finalPos.long.amount > 0 || finalPos.short.amount > 0) { Log("⚠️ 警告:仍有未平仓位!多头: " + finalPos.long.amount + ", 空头: " + finalPos.short.amount, "#FF0000"); if (finalPos.long.amount > 0) { exchange.CreateOrder(symbol, "closebuy", -1, finalPos.long.amount); } if (finalPos.short.amount > 0) { exchange.CreateOrder(symbol, "closesell", -1, finalPos.short.amount); } Sleep(1000); } else { Log("✅ 所有仓位已清空", "#00FF00"); } Log("========== 清仓完成 ==========", "#FF0000"); } function CheckStopLoss(equity) { if (stats.isStopLoss) { return true; } var threshold = stats.initialEquity * stopLossRatio; if (equity < threshold) { stats.isStopLoss = true; var lossPercent = ((stats.initialEquity - equity) / stats.initialEquity * 100).toFixed(2); Log("⚠️ 触发止损! 当前权益: " + _N(equity, 4) + " USDT, 损失: " + lossPercent + "%", "#FF0000"); return true; } return false; } function UpdateProfitChart(equity) { var profit = equity - stats.initialEquity; if (equity > stats.maxEquity) { stats.maxEquity = equity; } var drawdown = (stats.maxEquity - equity) / stats.maxEquity * 100; if (drawdown > stats.maxDrawdown) { stats.maxDrawdown = drawdown; } LogProfit(_N(profit, 4), "&"); } function UpdateStatus(account, pos, depth, buyPrice, sellPrice, equity) { var runTime = (new Date().getTime() - stats.startTime) / 1000 / 60; var hours = Math.floor(runTime / 60); var mins = Math.floor(runTime % 60); var spread = sellPrice - buyPrice; var marketSpread = depth.Asks[0].Price - depth.Bids[0].Price; var profit = equity - stats.initialEquity; var profitPercent = (profit / stats.initialEquity * 100).toFixed(2); var drawdown = stats.maxEquity > 0 ? ((stats.maxEquity - equity) / stats.maxEquity * 100).toFixed(2) : 0; var longRatio = (pos.long.amount / maxPosition * 100).toFixed(1); var shortRatio = (pos.short.amount / maxPosition * 100).toFixed(1); var netPos = _N(pos.long.amount - pos.short.amount, amountPrecision); var table1 = { type: "table", title: "💰 账户信息", cols: ["项目", "数值"], rows: [ ["可用余额", _N(account.Balance, 4) + " USDT"], ["冻结余额", _N(account.FrozenBalance, 4) + " USDT"], ["当前权益", _N(equity, 4) + " USDT"], ["初始权益", _N(stats.initialEquity, 4) + " USDT"], ["最高权益", _N(stats.maxEquity, 4) + " USDT"] ] }; var table2 = { type: "table", title: "📈 收益统计", cols: ["项目", "数值"], rows: [ ["累计收益", _N(profit, 4) + " USDT"], ["收益率", profitPercent + " %"], ["最大回撤", drawdown + " %"], ["止损阈值", (stopLossRatio * 100) + " %"], ["止损状态", stats.isStopLoss ? "⚠️ 已触发" : "✅ 正常"] ] }; var longStatus, shortStatus; if (longRatio > 120) { longStatus = "🔴 紧急减仓"; } else if (longRatio > 100) { longStatus = "🟠 超标"; } else if (longRatio > 80) { longStatus = "🟡 控量"; } else { longStatus = "🟢 正常"; } if (shortRatio > 120) { shortStatus = "🔴 紧急减仓"; } else if (shortRatio > 100) { shortStatus = "🟠 超标"; } else if (shortRatio > 80) { shortStatus = "🟡 控量"; } else { shortStatus = "🟢 正常"; } var table3 = { type: "table", title: "📊 持仓信息(仓位矫正)", cols: ["方向", "数量", "上限", "使用率", "状态", "浮盈"], rows: [ ["多头", pos.long.amount, maxPosition, longRatio + "%", longStatus, _N(pos.long.profit, 4)], ["空头", pos.short.amount, maxPosition, shortRatio + "%", shortStatus, _N(pos.short.profit, 4)], ["净仓", netPos, "-", "-", netPos > 0 ? "偏多" : (netPos < 0 ? "偏空" : "均衡"), "-"] ] }; var table4 = { type: "table", title: "🎯 做市信息", cols: ["项目", "数值"], rows: [ ["买一价", _N(depth.Bids[0].Price, pricePrecision)], ["卖一价", _N(depth.Asks[0].Price, pricePrecision)], ["盘口价差", _N(marketSpread, pricePrecision)], ["挂单买价", _N(buyPrice, pricePrecision)], ["挂单卖价", _N(sellPrice, pricePrecision)], ["做市价差", _N(spread, pricePrecision)] ] }; var table5 = { type: "table", title: "⏱️ 运行统计", cols: ["项目", "数值"], rows: [ ["运行时间", hours + "时" + mins + "分"], ["循环次数", stats.cycleCount], ["下单次数", stats.orderCount], ["撤单次数", stats.cancelCount], ["休眠时间", sleeptime + " ms"] ] }; var table6 = { type: "table", title: "⚙️ 精度与参数", cols: ["参数", "值"], rows: [ ["交易符号", symbol], ["价格精度", pricePrecision], ["数量精度", amountPrecision], ["最小下单量", minQty], ["价格步长", tickSize], ["基础下单量", baseAmount], ["最大持仓量", maxPosition], ["退出时清仓", closeOnExit ? "✅ 是" : "❌ 否"] ] }; var statusIcon = stats.isStopLoss ? "🛑 已止损" : (IsPositionOverload(pos) ? "⚠️ 仓位超标" : "🤖 运行中"); var statusStr = statusIcon + " | " + _D() + " | 收益: " + _N(profit, 2) + " USDT (" + profitPercent + "%)\n"; statusStr += "多仓: " + pos.long.amount + "/" + maxPosition + " (" + longRatio + "%) | "; statusStr += "空仓: " + pos.short.amount + "/" + maxPosition + " (" + shortRatio + "%) | 净: " + netPos + "\n"; statusStr += "`" + JSON.stringify([table1, table2, table3, table4, table5, table6]) + "`"; LogStatus(statusStr); } // 主交易逻辑 function onTick() { stats.cycleCount++; CleanLogs(); var depth = _C(exchange.GetDepth); if (!depth || !depth.Bids || !depth.Asks || depth.Bids.length < 20 || depth.Asks.length < 20) { Log("深度数据不足,跳过本轮"); Sleep(1000); return; } var account = _C(exchange.GetAccount); var pos = GetPosition(); var equity = GetEquity(account, pos); stats.currentEquity = equity; if (stats.cycleCount % 10 === 0) { UpdateProfitChart(equity); } var buyPrice = GetPrice("Buy", depth); var sellPrice = GetPrice("Sell", depth); if ((sellPrice - buyPrice) <= diffprice) { // buyPrice = NormalizePrice(buyPrice - 10 * tickSize); // sellPrice = NormalizePrice(sellPrice + 10 * tickSize); buyPrice = NormalizePrice(buyPrice - diffprice/2); sellPrice = NormalizePrice(sellPrice + diffprice/2); } UpdateStatus(account, pos, depth, buyPrice, sellPrice, equity); if (CheckStopLoss(equity)) { if (pos.long.amount > 0 || pos.short.amount > 0) { CloseAllPositions("止损触发"); } else { CancelPendingOrders(); } Log("策略已止损,停止交易。如需继续,请手动重启策略。", "#FF0000"); return; } CancelPendingOrders(); EmergencyReduce(pos, depth); pos = GetPosition(); var openLongAmount = CalcOpenAmount(pos, "long"); var openShortAmount = CalcOpenAmount(pos, "short"); var closeLongAmount = CalcCloseAmount(pos, "long"); var closeShortAmount = CalcCloseAmount(pos, "short"); var closeLongPrice = CalcClosePrice(pos, depth, "long"); var closeShortPrice = CalcClosePrice(pos, depth, "short"); if (openLongAmount > 0 && CheckFunds(account, buyPrice, openLongAmount)) { var orderId = exchange.CreateOrder(symbol, "buy", buyPrice, openLongAmount); if (orderId) stats.orderCount++; } if (pos.short.amount > 0 && closeShortAmount > 0) { var orderId = exchange.CreateOrder(symbol, "closesell", closeShortPrice, closeShortAmount); if (orderId) stats.orderCount++; } if (openShortAmount > 0 && CheckFunds(account, sellPrice, openShortAmount)) { var orderId = exchange.CreateOrder(symbol, "sell", sellPrice, openShortAmount); if (orderId) stats.orderCount++; } if (pos.long.amount > 0 && closeLongAmount > 0) { var orderId = exchange.CreateOrder(symbol, "closebuy", closeLongPrice, closeLongAmount); if (orderId) stats.orderCount++; } } // 初始化交易精度 function InitPrecision() { try { var markets = exchange.GetMarkets(); if (markets && markets[symbol]) { var market = markets[symbol]; // 获取基础精度信息 pricePrecision = market.PricePrecision || 2; tickSize = market.TickSize || 0.01; minQty = market.MinQty || 0.001; // 从 MinQty 推断数量精度 // 例如: MinQty=0.005 -> 精度3, MinQty=0.0001 -> 精度4 var minQtyPrecision = GetPrecisionFromValue(minQty); // 从 TickSize 推断价格精度(作为备选验证) var tickSizePrecision = GetPrecisionFromValue(tickSize); // 数量精度取 AmountPrecision 和 MinQty推断精度 的较小值 var declaredAmountPrecision = market.AmountPrecision || 8; amountPrecision = Math.min(declaredAmountPrecision, minQtyPrecision); // 价格精度取 PricePrecision 和 TickSize推断精度 的较小值 pricePrecision = Math.min(pricePrecision, tickSizePrecision); Log("========== 精度信息 =========="); Log("市场返回 - PricePrecision:", market.PricePrecision, ", AmountPrecision:", market.AmountPrecision); Log("市场返回 - TickSize:", tickSize, ", MinQty:", minQty); Log("推断精度 - TickSize精度:", tickSizePrecision, ", MinQty精度:", minQtyPrecision); Log("最终使用 - 价格精度:", pricePrecision, ", 数量精度:", amountPrecision); Log("=============================="); // 检查 baseAmount 是否满足最小下单量 if (baseAmount < minQty) { Log("⚠️ 警告: baseAmount(" + baseAmount + ") 小于最小下单量(" + minQty + "),已自动调整", "#FF9900"); baseAmount = minQty; } // 规范化 baseAmount baseAmount = NormalizeAmount(baseAmount); if (baseAmount === 0) { baseAmount = minQty; } Log("规范化后 baseAmount:", baseAmount); } } catch (e) { Log("获取精度失败,使用默认值: " + e.message, "#FF9900"); } } // 初始化收益图表 function InitChart() { var chart = { __isStock: true, tooltip: { xDateFormat: '%Y-%m-%d %H:%M:%S, %A' }, title: { text: '高频做市策略收益曲线' }, xAxis: { type: 'datetime' }, yAxis: { title: { text: '收益 (USDT)' }, opposite: false }, series: [{ name: '收益', data: [] }] }; Chart(chart); } // 程序入口 function main() { LogReset(LOG_RESERVE_COUNT); LogProfitReset(); InitChart(); exchange.SetContractType("swap"); symbol = exchange.GetCurrency() + ".swap"; Log("交易符号:", symbol); // 测试是否支持Lighter if (!exchange.GetAccount()) { Log("账户初始化失败,请检查配置是否正确,托管者是否为最新版本!") } InitPrecision(); stats.startTime = new Date().getTime(); stats.lastLogCleanTime = stats.startTime; var initAccount = _C(exchange.GetAccount); var initPos = GetPosition(); stats.initialEquity = GetEquity(initAccount, initPos); stats.maxEquity = stats.initialEquity; stats.currentEquity = stats.initialEquity; Log("========== 策略启动 ==========", "#00FF00"); Log("初始权益:", _N(stats.initialEquity, 4), "USDT"); Log("止损阈值:", _N(stats.initialEquity * stopLossRatio, 4), "USDT", "(" + (stopLossRatio * 100) + "%)"); Log("最大持仓:", maxPosition); Log("退出时清仓:", closeOnExit ? "是" : "否"); Log("初始账户:", initAccount); Log("初始持仓:", _C(exchange.GetPositions, symbol)); while (true) { try { onTick(); } catch (e) { Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message, "#FF0000"); } Sleep(sleeptime); } } // 退出清理 function onexit() { Log("========== 策略停止 ==========", "#FF0000"); if (closeOnExit) { Log("closeOnExit=true,执行退出清仓...", "#FF9900"); CloseAllPositions("策略退出"); } else { Log("closeOnExit=false,保留当前持仓和挂单", "#0000FF"); } Log("----------------------------------------"); Log("总循环: " + stats.cycleCount + ", 下单: " + stats.orderCount + ", 撤单: " + stats.cancelCount); Log("初始权益: " + _N(stats.initialEquity, 4) + " USDT"); Log("最终权益: " + _N(stats.currentEquity, 4) + " USDT"); Log("总收益: " + _N(stats.currentEquity - stats.initialEquity, 4) + " USDT"); Log("收益率: " + _N((stats.currentEquity - stats.initialEquity) / stats.initialEquity * 100, 2) + " %"); Log("最大回撤: " + _N(stats.maxDrawdown, 2) + " %"); Log("----------------------------------------"); }

img

FMZのパラメータ編集ルールをAIに伝えると、AIがインターフェースパラメータを直接設定してくれます。説明のために、上の写真のように戦略インターフェースでパラメータを手動で設定しました。

4. ライブ取引

img

img

img

正直、AIが書いたコードは私のものよりはるかに良くて、間違いもほとんどありません(要件さえ明確に記述されていれば、3〜4回の反復処理で安定して動作させることができています)。生産性が爆発的に上がった気がします💥 今のところ戦略で儲かっていないようですが😂、取引量はかなり増えました。

img

img

5. まとめ

FMZ + AI + ライターの化学反応

この経験を振り返ってみると、いくつか考えがあります。

  • 手数料ゼロはまさにゲームチェンジャーだ
    過去には理論的に健全だった多くの戦略が、「見えない殺し屋」である取引手数料によって打ち負かされてきました。ライターの手数料無料政策は、これらの戦略に復活のチャンスを与えました。もしあなたが同様の「休眠中の戦略」をお持ちなら、掘り出して試してみるのも良いでしょう。

  • AIは戦略策定の障壁を大幅に下げました。
    今回はほとんど手作業でコードを書かず、戦略の再構築はすべてAIで完了しました。これは以前は考えられなかったことです。トレードのアイデアはあってもプログラミングスキルが限られている人にとって、AIとFMZの組み合わせは間違いなく大きなメリットとなります。

  • FMZの新しい取引所との迅速な統合の価値
    FMZはLighterのような新興取引所と迅速に連携できるため、ユーザーは即座にチャンスを掴むことができます。また、統合APIにより、戦略を新しいプラットフォームに簡単に移行できます。

次のステップ

次に、次のことを計画しています。

  • この戦略のパラメータを最適化し続けます。
  • 手数料ゼロの環境に適した戦略タイプをさらに試してください。
  • Lighter に適用可能な関連戦略を調べます。

その他の古代の戦略には、「OK Leek Harvester」などがあります。

ご支援ありがとうございます。

ご覧いただきありがとうございます。ご意見・ご要望などございましたらお気軽にお寄せください。

6. 免責事項

この記事は技術的な情報交換と学習のみを目的としており、いかなる投資アドバイスも構成するものではありません。

  • 戦略リスク:この記事で紹介する戦略コードは、テクニカル分析のみを目的としており、収益性を保証するものではありません。クオンツ取引には本質的にリスクが伴い、過去のバックテストや短期のライブ取引のパフォーマンスは将来のリターンを示唆するものではありません。本戦略は、そのロジックを十分に理解した上で、慎重にご利用ください。
  • DEXのリスク:分散型取引所(DEX)には、スマートコントラクトリスク、流動性リスク、ネットワーク輻輳リスクが伴います。新興プラットフォームであるLighter DEXの長期的な安定性とセキュリティは、市場による検証がまだ完了していません。
  • 取引手数料無料ポリシー:取引所手数料ポリシーは随時変更される場合があります。Lighterの最新の公式発表をご確認ください。取引手数料が無料の場合でも、オンチェーンガス料金が発生する場合があります。
  • AI生成コード:この記事の戦略コードはAIの支援を受けて生成されました。テスト済みですが、潜在的なバグや論理的な欠陥が存在する可能性があります。学習および研究目的のみに使用してください。
  • ユーザーはすべてのリスクを負います。本記事で提供される情報、コード、または戦略の使用から生じるあらゆる結果については、ユーザーが単独で責任を負います。著者およびFMZプラットフォームは、いかなる直接的または間接的な損失についても責任を負いません。

暗号通貨取引には高いリスクが伴います。リスク管理を徹底し、合理的な取引を行ってください。

Comment
All comments (9)

    高频的话没意义,强制延迟300Ms

    2 months ago

    梦神,你的这个直接可以回测吗?我回测时候,提醒需求太多。GetAccount: {"msg":"Too Many Requests","code":"50011"} at onTick (FILE:541:21) at main (FILE:709:19)
    策略的参数怎么调整会比较好。可以给点建议吗?谢谢

    5 months ago

    写个WebSocket模板订阅公共频道访问深度,然后替换exchange.GetDepth接口

    5 months ago

    具体有没有代码,可以帮忙提供一下。我卡在这里了。谢谢

    5 months ago

    对于这个策略,回测测不出来什么,只能实盘测,实盘还需要优化,我实盘测试不能盈利,但是量倒是刷了不少。。。

    5 months ago

    我就是实盘测试的,出现这种问题。

    5 months ago

    有些接口前增加一些Sleep(1000),交易所有些限频,不能访问接口太快。可以让AI帮你改,给AI说访问频率过高,降低频率或者合理减少接口调用。

    5 months ago

    好东西,大道至简

    5 months ago

    感谢老铁的支持,继续分享有趣的量化交易实践经验。

    5 months ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)