[TOC]

Mới đây, nền tảng định lượng FMZ đã chính thức được tích hợp.Lighter DEXThành thật mà nói, lúc đầu tôi không mấy chú ý đến tin tức này – dù sao thì trên thị trường cũng có vô số sàn giao dịch phi tập trung (DEX). Nhưng sau khi tìm hiểu thêm, một tính năng đã thu hút sự chú ý của tôi: phí giao dịch bằng không.
Đúng vậy, bạn không đọc nhầm đâu. Lighter DEX cung cấp phí hoa hồng bằng 0 cho các nhà giao dịch thông thường. Điều này ngay lập tức nhắc nhở tôi về một điều: liệu cuối cùng tôi có thể sử dụng lại những chiến lược mà tôi đã “gác lại” nhiều năm trước vì chi phí hoa hồng không? Vì vậy, tôi đã mở FMZ…Quảng trường Chiến lượcTìm kiếm các chiến lược từ “thời xa xưa”…
Tôi sẽ không đi sâu vào chi tiết về sàn giao dịch phi tập trung (DEX) mới này; những ai quan tâm có thể tìm kiếm thêm thông tin để tìm hiểu thêm. Hiện tại, trải nghiệm người dùng khá tốt. Về trải nghiệm người dùng, Lighter cung cấp hiệu suất tương đương với các sàn giao dịch tập trung trong khi vẫn duy trì tính minh bạch phi tập trung, và nó vẫn tương đối ổn định ngay cả khi truy cập API với tần suất cao.
Dưới đây là một số thông tin đã được tổng hợp:
Tiếp theo, tôi sẽ giới thiệu ngắn gọn cách cấu hình FMZ.LighterThêm thông tin cấu hình Khóa API Lighter vào trang trao đổi của nền tảng FMZ.

Cần cấu hình ba mục sau:

Được tạo raKhóa riêng tư chữ kýViệc cấu hình có thể được thực hiện trong hộp chỉnh sửa điều khiển tương ứng trên trang FMZ Add Exchange.
Lưu ý quan trọng: Bạn cần tải xuống phiên bản mới nhất của chương trình quản lý tài sản để hỗ trợ giao dịch hợp đồng tương lai Lighter.
Chỉ mục API Nhập chỉ số tương ứng với khóa riêng dùng để ký.
Chỉ mục tài khoản Bạn có thể lấy chỉ mục tài khoản thông qua API của Lighter:
https://mainnet.zklighter.elliot.ai/api/v1/account?by=l1_address&value={钱包地址}
Ví dụ, truy cập trực tiếp địa chỉ đó trong trình duyệt:https://mainnet.zklighter.elliot.ai/api/v1/account?by=l1_address&value=0x123xxxx,0x123xxxxĐây chỉ là địa chỉ ví dụ; hãy thay thế nội dung này khi sử dụng trong thực tế.
Dữ liệu trả về:{
"code": 200,
"total": 1,
"accounts": [
{
"code": 0,
"account_type": 0,
"index": 1234567,
"l1_address": "0x123xxxx",
TRONG"index": 1234567Đó là chỉ số tài khoản của bạn.
Quá trình tạo lập ban đầu chỉ bắt đầu khi tài sản (như USDC) được chuyển vào.Lightertài khoản
Lưu ý rằng giao diện thu được bằng điểm cuối mainnet sẽ truy xuất chỉ mục tài khoản mainnet, trong khi giao diện thu được bằng điểm cuối testnet sẽ truy xuất chỉ mục tài khoản testnet.
Tại sao chúng ta cần điền vào mục lục tài khoản này? Bởi vìLighterHệ thống này có chức năng phân chia tài khoản thành nhiều tài khoản dựa trên chỉ số tài khoản. Nếu cần sử dụng tài khoản phụ, bạn có thể cấu hình chỉ số tài khoản phụ tại đây (chỉ số tài khoản phụ sẽ xuất hiện trong dữ liệu JSON được trả về bởi liên kết truy vấn ở trên).
Đây là tính năng khiến tôi hào hứng nhất. Lighter cung cấp chính sách miễn phí giao dịch cho các nhà giao dịch thông thường.
Các chiến lược giao dịch tần suất cao không còn bị “mất mát” lợi nhuận do phí giao dịch nữa. Chiến lược lưới cho phép thiết lập khoảng cách lưới dày đặc hơn. Điểm hòa vốn đối với các chiến lược kinh doanh chênh lệch giá đã giảm đáng kể. Những chiến lược “về mặt lý thuyết là khả thi nhưng trên thực tế lại bị cản trở bởi phí giao dịch” cuối cùng đã tìm được chỗ đứng để áp dụng.
Với câu hỏi trong đầu, “Những chiến lược nào có thể được khôi phục với phí giao dịch bằng không?”, tôi bắt đầu tìm kiếm trong thư viện chiến lược và cộng đồng FMZ. Chẳng mấy chốc, một chiến lược quen thuộc đã thu hút sự chú ý của tôi:
Chiến lược này đơn giản và dễ thực hiện, nhưng trong môi trường có phí giao dịch, nó hầu như luôn dẫn đến thua lỗ. Tuy nhiên, trong môi trường không phí giao dịch của Lighter, nó đáng để thử.
Vấn đề ở đây là: mã nguồn quá cũ. Xét về chiến lược, mã nguồn đơn giản và thô sơ, hầu như không có nội dung giao diện người dùng và thiếu một số tính năng hỗ trợ tiếp cận. Dưới đây là một vài ví dụ về những gì còn thiếu:
Tự tay viết lại mã nguồn này ư? Thành thật mà nói, điều đó khá khó khăn. Tuy nhiên, tôi đã nghĩ ra một giải pháp “lười biếng” - hãy để AI làm việc đó thay tôi.
Trước tiên, hãy thiết lập một biện pháp bảo vệ: bài viết này chỉ là một nỗ lực thăm dò nhằm tái cấu trúc một chiến lược sử dụng trí tuệ nhân tạo trên một sàn giao dịch phi tập trung (DEX) mới nổi, và chúng tôi không đảm bảo tính sinh lời của chiến lược được tái cấu trúc. Vì vậy, hãy bắt đầu tái cấu trúc chiến lược cổ xưa này bằng Claude. Tôi không muốn viết mã từ đầu; yêu cầu của tôi là:
Tôi đã sao chép mã chiến lược gốc và gửi kèm theo yêu cầu của mình cho AI. Sau nhiều vòng đối thoại và điều chỉnh, AI đã tạo ra mã được chỉnh sửa lại cho tôi:
- bash: while :; do cat PROMPT.md | claude-code ; done
- ) (Những điều cần suy ngẫm)
/*
高频做市策略 - 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("----------------------------------------");
}

Bạn chỉ cần cho AI biết các quy tắc chỉnh sửa tham số trên FMZ, và AI thậm chí có thể tự động cấu hình tất cả các tham số giao diện cho bạn. Để dễ hình dung, tôi đã tự cấu hình các tham số trên giao diện chiến lược, như hình ảnh phía trên.



Thành thật mà nói, mã do AI viết tốt hơn nhiều so với của tôi, và nó hiếm khi mắc lỗi (miễn là các yêu cầu được mô tả rõ ràng, tôi chỉ cần lặp lại 3-4 lần là nó chạy ổn định). Tôi cảm thấy năng suất của mình đã tăng vọt 💥 Mặc dù có vẻ như chiến lược này chưa kiếm được tiền ngay bây giờ 😂, nhưng khối lượng giao dịch đã tăng lên đáng kể.


Nhìn lại trải nghiệm này, tôi có một vài suy nghĩ:
Miễn phí giao dịch thực sự là một bước đột phá. Nhiều chiến lược từng được cho là khả thi về mặt lý thuyết đã bị đánh bại bởi “kẻ giết người vô hình” là phí giao dịch. Chính sách không phí của Lighter đã mang lại cho những chiến lược này cơ hội hồi sinh. Nếu bạn có những “chiến lược tiềm ẩn” tương tự, bạn có thể muốn tìm lại chúng và thử áp dụng.
Trí tuệ nhân tạo đã làm giảm đáng kể rào cản trong việc xây dựng chiến lược. Lần này, tôi hầu như không phải viết bất kỳ đoạn mã nào bằng tay; toàn bộ quá trình tái cấu trúc chiến lược được hoàn thành bằng trí tuệ nhân tạo (AI). Điều này trước đây là không thể tưởng tượng nổi. Đối với những người có ý tưởng giao dịch nhưng kỹ năng lập trình hạn chế, sự kết hợp giữa AI và FMZ chắc chắn là một lợi thế lớn.
Giá trị của việc FMZ nhanh chóng hội nhập với các sàn giao dịch mới. FMZ có thể nhanh chóng tích hợp với các sàn giao dịch mới nổi như Lighter, cho phép người dùng nắm bắt cơ hội ngay lập tức. API thống nhất cũng có nghĩa là chiến lược của bạn có thể dễ dàng được chuyển sang các nền tảng mới.
Tiếp theo, tôi dự định:
Các chiến lược cổ xưa khác bao gồm: Máy thu hoạch tỏi tây OK, v.v.
Cảm ơn bạn đã đọc. Vui lòng cho chúng tôi biết bất kỳ đề xuất hoặc yêu cầu nào của bạn.
Bài viết này chỉ nhằm mục đích trao đổi kiến thức và học hỏi kỹ thuật, không phải là lời khuyên đầu tư.
Giao dịch tiền điện tử tiềm ẩn rủi ro cao. Hãy đảm bảo quản lý rủi ro và giao dịch một cách hợp lý.