[TOC]

最近FMZ量化平台正式接入了Lighter DEX。说实话,刚看到这个消息时我并没有太在意——毕竟市面上的DEX多如牛毛。但当我仔细了解后,一个特性让我眼前一亮:零手续费。
对,你没看错。Lighter DEX对普通交易者实行零手续费政策。这让我立刻想到了一件事:那些年因为手续费损耗而被我”雪藏”的策略,是不是可以翻出来重见天日了?于是,我打开了FMZ的策略广场,翻找那些”远古时代”的策略…
关于这个新增的DEX,我也不做过多介绍,有兴趣的可以查阅一些资料了解,目前使用体验是比较好的。使用体验方面感受到Lighter在拥有中心化交易所级别的性能,同时保持了去中心化的透明性,对于API接口高频访问时也比较稳定。
这里整理了一些资料:
接下来简单介绍一下如何在FMZ上配置Lighter,在FMZ平台添加交易所页面添加Lighter的API KEY配置信息。

需要配置3个内容:

将创建好的签名私钥配置在FMZ添加交易所页面中对应控件编辑框中即可。
重要提示: 需要下载最新版本的托管者程序才支持 Lighter 期货合约交易所。
API索引 填写签名私钥对应的索引。
账户索引 账户索引可以通过Lighter的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=0x123xxxx,0x123xxxx是我举例的地址,具体使用时替换这个内容。
返回数据:{
"code": 200,
"total": 1,
"accounts": [
{
"code": 0,
"account_type": 0,
"index": 1234567,
"l1_address": "0x123xxxx",
其中"index": 1234567就是你的账户索引。
为什么要填写这个账户索引,因为Lighter有子账户系统,根据账户索引区分不同账户,如果需要使用子账户,在这里配置子账户的账户索引即可(子账户的账户索引会出现在以上查询链接返回的JSON数据中)。
这是最让我兴奋的特性。Lighter对普通交易者实行零手续费政策。
高频策略不再被手续费”吃掉”利润 网格策略可以设置更密的网格间距 套利策略的盈亏平衡点大幅降低 那些”理论上可行但实际被手续费打败”的策略,终于有了用武之地
带着”零手续费能让什么策略复活”的想法,我开始在FMZ策略库和社区里翻找。很快,一个熟悉的策略进入了我的视野:
这个策略简单暴力,但是在有手续费的环境下,基本100%亏损。但在Lighter的零手续费环境下,是可以尝试一下的。
那么问题来了,代码太老了。翻出策略一看,代码简单暴力,UI显示内容几乎没有,缺少一些辅助功能等,以下列举几个缺少的内容:
要手动重构这些代码?说实话,有点头大。不过,我想到了一个”偷懒”的办法——让AI来帮我重构。
先开个“护盾”,本文只是对于新兴DEX交易所+AI重构策略做一次探索尝试,不确保重构后的策略具有多强的盈利能力。那么我们开始使用Claude重构这个远古策略,我不想从零开始写代码,我的需求是:
我把原始策略代码复制出来,连同我的需求一起发给了AI。经过几轮对话和调整,AI帮我生成了重构后的代码:
- bash: while :; do cat PROMPT.md | claude-code ; done
- ) (借鉴思路)
/*
高频做市策略 - 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("----------------------------------------");
}

你把FMZ上参数的编辑规则告诉AI,甚至AI直接帮你把界面参数都配置好,为了便于讲解我是手动去配置的策略界面上的参数,如上图。



说句实话,AI写的代码真的比我写得好太多,而且很少错的(只要需求描述清楚,我也就迭代了3~4次就跑稳定了),瞬间感觉生产力爆炸💥虽然目前看起来好像策略不赚钱😂,交易量倒是刷了不少。


回顾这次实践,我有几点感触:
零手续费确实是game changer 以前很多”理论很美好”的策略,都被手续费这个”隐形杀手”打败了。Lighter的零手续费政策,让这些策略有了重生的机会。如果你也有类似的”雪藏策略”,不妨翻出来试试。
AI大幅降低了策略开发门槛 这次我几乎没有手写代码,全程依靠AI完成了策略重构。这在以前是不可想象的。对于有交易思路但编程能力有限的朋友来说,AI+FMZ的组合无疑是一个福音。
FMZ快速接入新交易所的价值 FMZ能够快速接入Lighter这样的新兴交易所,让用户可以第一时间抓住机会。统一的API封装也意味着,你的策略可以很容易地迁移到新平台。
接下来,我打算: - 继续优化这个策略的参数。 - 尝试更多适合零手续费环境的策略类型。 - 探索Lighter的适用的相关策略。
其它远古策略,还有:OK韭菜收割机等。
感谢您的阅读,如果您有好的需求和建议欢迎提出。
本文仅供技术交流与学习参考,不构成任何投资建议。
加密货币交易具有高风险性,请务必做好风险管理,理性交易。