2
tập trung vào
410
Người theo dõi

Trò chơi phiêu lưu: Triển khai mã và ứng dụng chiến lược cuộn chuột

Được tạo ra trong: 2025-12-19 17:06:01, cập nhật trên: 2025-12-29 09:04:46
comments   0
hits   353

[TOC]

Trò chơi phiêu lưu: Triển khai mã và ứng dụng chiến lược cuộn chuột

giới thiệu

Trong lĩnh vực giao dịch định lượng, chiến lược vị thế luân chuyển là một chủ đề hấp dẫn nhưng cũng đầy thách thức. Ý tưởng cốt lõi của chiến lược này là đạt được tăng trưởng kép bằng cách tái đầu tư lợi nhuận thu được vào các thị trường đang có xu hướng. Bài viết này sẽ đi sâu vào cách chuyển đổi ý tưởng giao dịch này thành mã logic có thể thực thi từng bước một, tập trung vào sự thay đổi tư duy hơn là các chi tiết kỹ thuật. Điều quan trọng cần lưu ý là trong khi chiến lược vị thế luân chuyển khuếch đại lợi nhuận, nó cũng khuếch đại rủi ro; bài viết này chỉ dành cho mục đích học tập và thảo luận.


I. Phân tích chuyên sâu về logic lợi nhuận của chiến lược vị thế luân chuyển

1.1 Bản chất toán học của hiện tượng tràn số

Sơ đồ cuộn

Logic lợi nhuận của chiến lược vị thế luân chuyển về cơ bản là…Mô hình tăng trưởng képChúng ta hãy cùng hiểu điều này thông qua một ví dụ đơn giản:

Giao dịch đơn lẻ truyền thống (3 lần tăng liên tiếp, mỗi lần 10%):

  • Vốn ban đầu: 100 USDT, đòn bẩy 3x
  • Mức tăng thị trường: (1+10%) × (1+10%) × (1+10%) - 1 = 33,1%
  • Lợi nhuận: 100 × 3 × 33,1% = 99,3 USDT
  • Giá cuối cùng: 199,3 USDT

Giao dịch tích lũy (ba giao dịch liên tiếp, mỗi giao dịch tăng 10%):

  • Lần đầu tiên100 USDT → Lãi 30 USDT → Số tiền còn lại là 130 USDT
    • Tính toán: 100 × đòn bẩy 3x × mức tăng 10% = 30
  • Lần thứ 2130 USDT → Lợi nhuận 39 USDT → Số tiền còn lại là 169 USDT
    • Tính toán: 130 × đòn bẩy 3x × mức tăng 10% = 39
  • Thứ 3169 USDT → Lợi nhuận 50,7 USDT → Số dư tăng lên 219,7 USDT
    • Tính toán: 169 × đòn bẩy 3x × mức tăng 10% = 50,7

Kết quả so sánh:

Trong trường hợp tương tự, nếu thị trường tăng 10% ba lần liên tiếp:

  • giao dịch đơn lẻLợi nhuận 99,3 USDT
  • Giao dịch chuyển đổiLợi nhuận 119,7 USDT
  • Ưu điểm của lãi kép20,4 USDT (tăng khoảng 20,5%)

Tương tự, với ba lần tăng liên tiếp 10% mỗi lần, lợi nhuận từ một giao dịch là 99,3 USDT và lợi nhuận từ việc chuyển tiếp vị thế là 119,7 USDT.Sự khác biệt này chính là sức mạnh của lãi kép.

Được biểu diễn bằng công thức toán học:

// 传统交易:线性增长
最终资金 = 初始资金 × (1 + 杠杆 × 涨幅)

// 滚仓交易:指数增长
最终资金 = 初始资金 × (1 + 杠杆 × 单次涨幅) ^ 滚仓次数

Điều này cho thấy bản chất của việc chuyển đổi:Chuyển đổi tăng trưởng tuyến tính thành tăng trưởng theo cấp số mũTuy nhiên, điều này cũng tiềm ẩn những rủi ro:Một lệnh cắt lỗ duy nhất có thể xóa sạch toàn bộ lợi nhuận tích lũy trước đó.

1.2 Ba vấn đề cốt lõi của chiến lược chuyển đổi

Trước khi bắt đầu viết bất kỳ đoạn mã nào, chúng ta cần trả lời ba câu hỏi cơ bản từ góc độ chiến lược:

Câu hỏi 1: Khi nào nó bắt đầu? (Mục nhập đầu tiên)
Việc xác định tín hiệu khởi đầu của một xu hướng là điều cần thiết.

Câu hỏi 2: Khi nào nên tiếp tục? (Vị trí lăn bổ sung)
Đây là cốt lõi của việc chuyển đổi vị thế: làm thế nào để xác định liệu xu hướng có tiếp tục sau khi chốt lời hay không.

Câu hỏi 3: Khi nào nên dừng lại? (Rút lui và quan sát)

  • Rút lui chủ động: Xu hướng suy yếu
  • Thoát lệnh thụ động: kích hoạt lệnh dừng lỗ

Ba câu hỏi này xác định khuôn khổ của toàn bộ chiến lược, và bây giờ chúng ta sẽ chuyển chúng thành mã logic từng câu một.


II. Câu hỏi 1: Khi nào nên bắt đầu? — Tìm điểm bùng phát để gia nhập thị trường.

Kích hiệu vào cửa

2.1 Lý tưởng và thực tế của chiến lược chuyển đổi

Trước tiên, chúng ta hãy cùng tìm hiểu kịch bản ứng dụng lý tưởng cho chiến lược vị thế luân chuyển.

Tình huống lý tưởng:
Hãy tưởng tượng nếu bạn có thể tham gia thị trường SHIB ngay khi nó bắt đầu tăng từ 0,000001 đô la, hoặc thiết lập vị thế ngay trước khi một altcoin nào đó tăng vọt. Thông qua việc liên tục chuyển đổi, 100 USDT có thể trở thành 10.000 USDT hoặc thậm chí nhiều hơn. Đây chính là giấc mơ cuối cùng của chiến lược chuyển đổi —Hãy tham gia thị trường trước khi tiền điện tử bùng nổ và thu về lợi nhuận gấp mười, thậm chí trăm lần.

Thực tế phũ phàng:
Vấn đề là, làm sao bạn biết được loại tiền điện tử nào sẽ tăng giá mạnh? Và khi nào nó sẽ tăng giá?

  • Nếu bạn là chủ dự án hoặc người nội bộ, bạn có thể đã biết trước những tin tức tích cực.
  • Nếu bạn là một nhà giao dịch thông thường, bạn chỉ có thể đưa ra phán đoán dựa trên tín hiệu thị trường.

Đối với hầu hết chúng ta, việc nắm bắt chính xác điểm bước ngoặt này là…Nói thẳng ra, tất cả đều phụ thuộc vào may mắn.Chúng ta không thể dự đoán tương lai; chúng ta chỉ có thể cố gắng tăng xác suất “trúng số độc đắc” bằng cách sử dụng dữ liệu lịch sử và các chỉ báo kỹ thuật.

2.2 Từ lý tưởng đến thực tế: Mô phỏng điểm vào lệnh dựa trên các chỉ báo kỹ thuật

Vì chúng ta không thể dự đoán loại tiền điện tử nào sẽ tăng giá mạnh, tất cả những gì chúng ta có thể làm là:Thiết lập một bộ quy tắc vào lệnh khả thi và sử dụng các chỉ báo kỹ thuật để mô phỏng tín hiệu “bắt đầu xu hướng”.

Nó giống như việc câu cá giữa đại dương bao la. Mặc dù chúng ta không biết cá lớn ở đâu, nhưng chúng ta có thể:

  • Hãy quan sát những gợn sóng trên mặt nước (sự biến động giá cả).
  • Phân tích hướng dòng chảy của nước (hướng xu hướng).
  • Chọn các công cụ phù hợp (chỉ số kỹ thuật)

Khi nhiều tín hiệu cùng hội tụ, chúng ta tin rằng một xu hướng có thể sắp bắt đầu, vì vậy chúng ta tham gia thị trường để thử nghiệm. Nếu đúng, chúng ta sẽ theo xu hướng và gia hạn vị thế để kiếm lời; nếu sai, chúng ta sẽ cắt lỗ và nhanh chóng rời khỏi thị trường.

2.3 Triển khai kỹ thuật tín hiệu vào

Lựa chọn công cụ kỹ thuật:
Chúng tôi sử dụng hệ thống đường trung bình động kép EMA (EMA5 và EMA10) làm công cụ xác định xu hướng. Lý do lựa chọn hệ thống này rất đơn giản:

  • Đơn giản, trực quan và dễ xác minh.
  • Có khả năng phản ứng nhanh chóng với sự thay đổi giá cả.
  • Các thông số cân bằng giữa độ nhạy và độ ổn định.

Nguyên tắc cốt lõi:
Bằng cách phát hiện “điểm giao cắt vàng” (EMA5 vượt lên trên EMA10) và “điểm giao cắt tử thần” (EMA5 vượt xuống dưới EMA10) của các đường trung bình động, có thể nắm bắt được các điểm đảo chiều xu hướng:

  • Mô hình giao cắt vàng → Tín hiệu mua
  • Mô hình giao cắt tử thần → Tín hiệu bán khống

Khái niệm về mã:

// 计算EMA指标
var emaFast = TA.EMA(records, FastEMA);  // EMA5
var emaSlow = TA.EMA(records, SlowEMA);  // EMA10

// 获取当前和前一根K线的EMA值
var ema5_current = emaFast[emaFast.length - 1];
var ema5_prev = emaFast[emaFast.length - 2];
var ema10_current = emaSlow[emaSlow.length - 1];
var ema10_prev = emaSlow[emaSlow.length - 2];

// 检测金叉:前一根K线EMA5<=EMA10,当前K线EMA5>EMA10
var bullCross = ema5_prev <= ema10_prev && ema5_current > ema10_current;

// 检测死叉:前一根K线EMA5>=EMA10,当前K线EMA5<EMA10
var bearCross = ema5_prev >= ema10_prev && ema5_current < ema10_current;

// 空仓时等待信号入场
if (bullCross) {
    Log("📈 金叉信号 - 做多");
    openPosition("LONG", currentPrice);
} else if (bearCross) {
    Log("📉 死叉信号 - 做空");
    openPosition("SHORT", currentPrice);
}

Phần này sẽ không đi sâu vào chi tiết về các tín hiệu giao cắt vàng và tín hiệu giao cắt tử thần; đây là những khái niệm cơ bản trong giao dịch. Điểm mấu chốt là:Chúng ta cần một tín hiệu vào lệnh rõ ràng, có thể định lượng được để kích hoạt quá trình chuyển đổi.


III. Câu hỏi 2: Khi nào nên tiếp tục? — Cơ chế cốt lõi của lãi kép.

Cơ chế lật

3.1 Hiểu được bản chất của việc lật bài: Một trò chơi phiêu lưu lý trí

Chiến lược chuyển đổi về cơ bản làMột trò chơi phiêu lưu hợp lýHãy cùng hiểu điều này thông qua một tình huống cụ thể:

Luật chơi:

1. 你从交易所账户中拿出100 USDT作为冒险资金
2. 这100 USDT独立管理,与账户其他资金隔离
3. 用这100 USDT开始交易:
   - 赚了 → 盈利加入资金池,继续用更大的资金交易(滚仓)
   - 亏了 → 触发止损,回到空仓状态
4. 重复这个过程,直到:
   - 要么把100 USDT亏完(游戏结束)
   - 要么滚到一个满意的金额(主动退出)

Sự xuất sắc của trò chơi này nằm ở chỗ:

  • Rủi ro có thể kiểm soát được: mức thua lỗ tối đa là 100 USDT, sẽ không ảnh hưởng đến số tiền khác trong tài khoản.
  • Lợi nhuận không giới hạn: Nếu xu hướng thuận lợi, lãi kép có thể nhanh chóng nhân đôi vốn của bạn.
  • Các quy tắc rõ ràng về điểm vào và điểm ra: quy tắc cụ thể về việc chốt lời, cắt lỗ và chuyển đổi vị thế.

3.2 Thiết kế quỹ vốn: Chìa khóa để đạt được lãi kép

Đây là khái niệm thiết kế cốt lõi của chiến lược vị thế luân chuyển.

Những vấn đề với các tập quán truyền thống:
Giả sử tài khoản giao dịch của bạn có 1000 USDT:

  • Vị thế đầu tiên được mở với 100 USDT.
  • Sau khi kiếm được lợi nhuận 30 USDT, số dư tài khoản trở thành 1030 USDT.
  • Tôi nên dùng bao nhiêu tiền cho vị trí mở lệnh thứ hai? 100 hay 130?
  • Làm thế nào để phân biệt lợi nhuận đến từ chiến lược vị thế luân chuyển hay từ các hoạt động khác?

Giải pháp huy động vốn chung:

// 创建一个虚拟的"策略资金池"
var strategyCapital = InitialCapital;  // 初始100 USDT

// 第1次交易
// 开仓金额 = 100 USDT
// 止盈后盈利 = 30 USDT
strategyCapital = strategyCapital + 30;  // 资金池变为130 USDT

// 第2次交易(滚仓)
var positionValue = strategyCapital * Leverage;  // 130 × 3 = 390
var amount = positionValue / price / ctVal;      // 计算开仓数量
// 自动使用了第1次的盈利,这就是复利的关键

// 止盈后盈利 = 39 USDT
strategyCapital = strategyCapital + 39;  // 资金池变为169 USDT

// 第3次交易(滚仓)
// 开仓金额 = 169 USDT(继续利滚利)

Ưu điểm của thiết kế này:

  • Phân tách quỹ:Chiến lược này chỉ sử dụng 100 USDT đã được chỉ định và không ảnh hưởng đến các khoản tiền khác trong tài khoản.
  • Lãi kép tự động:Mỗi khoản lợi nhuận sẽ tự động được cộng vào quỹ vốn, do đó một lượng vốn lớn hơn sẽ được sử dụng cho vị thế giao dịch tiếp theo.
  • Rủi ro có thể kiểm soát được:Trường hợp xấu nhất là mất 100 USDT, điều này nằm trong dự đoán.
  • Theo dõi rõ ràng:Nó có thể xác định chính xác chiến lược đã xoay vòng bao nhiêu từ 100 USDT.

3.3 Quyết định tiếp tục giao dịch: Tiếp tục hay dừng lại sau khi chốt lời?

Đây là yếu tố cốt lõi của chiến lược vị thế luân chuyển:Sau khi lệnh chốt lời được thực hiện, chúng ta cần đưa ra một quyết định quan trọng – tiếp tục giao dịch hay dừng lại?

Tình huống ra quyết định:

假设我们做多BTC:
- 入场价:45000 USDT,用100 USDT开仓
- 止盈价:49500 USDT(涨10%)
- 止盈成交,盈利30 USDT
- 现在资金池:130 USDT

问题来了:
选项A:收手,带着130 USDT退出,回到空仓
选项B:继续,用130 USDT再次开多(滚仓)

Cách lựa chọn như thế nào?

Quyết định này không thể dựa trên “cảm xúc”; phải có những tiêu chuẩn rõ ràng. Logic đánh giá của chúng tôi là:Xu hướng này có tiếp tục không?

Phương pháp đánh giá:
Ngay khi lệnh chốt lời được thực hiện, các chỉ báo kỹ thuật mới nhất (đường trung bình động EMA) sẽ được tính toán lại:

// 止盈单成交后,获取最新K线数据
var records = _C(exchange.GetRecords, PERIOD_M1);
var emaFast = TA.EMA(records, FastEMA);
var emaSlow = TA.EMA(records, SlowEMA);

var ema5_current = emaFast[emaFast.length - 1];
var ema10_current = emaSlow[emaSlow.length - 1];

var shouldRoll = false;

if (currentDirection == "LONG") {
    // 多头止盈后,如果EMA5仍在EMA10上方,继续做多(滚仓)
    if (ema5_current > ema10_current) {
        shouldRoll = true;
        Log("✅ EMA5 > EMA10,上升趋势未破坏");
        Log("🔄 决策:继续做多(滚仓)");
    } else {
        Log("❌ EMA5 <= EMA10,趋势可能转弱");
        Log("⏸️ 决策:不滚仓,等待新信号");
    }
} else if (currentDirection == "SHORT") {
    // 空头止盈后,如果EMA5仍在EMA10下方,继续做空(滚仓)
    if (ema5_current < ema10_current) {
        shouldRoll = true;
        Log("✅ EMA5 < EMA10,下降趋势未破坏");
        Log("🔄 决策:继续做空(滚仓)");
    } else {
        Log("❌ EMA5 >= EMA10,趋势可能转弱");
        Log("⏸️ 决策:不滚仓,等待新信号");
    }
}

3.4 Quy trình thực hiện chuyển đổi

Nếu quyết định là “tiếp tục giữ nguyên vị thế”:

if (shouldRoll) {
    // 1. 增加滚仓计数
    currentRoundRolls++;
    
    Log("🔄 执行滚仓操作... (本轮第", currentRoundRolls, "次滚仓)");
    
    // 2. 获取最新价格
    var ticker = _C(exchange.GetTicker);
    var newPrice = ticker.Last;
    
    // 3. 基于新资金池重新开仓
    if (openPosition(currentDirection, newPrice)) {
        Log("✅ 滚仓成功!");
        // 4. 挂新的止盈单(在openPosition函数中完成)
        // 5. 设置新的止损价(在checkStopLoss函数中监控)
    } else {
        Log("❌ 滚仓失败,等待新信号");
        saveRollRecord(false);
        resetPositionState();
    }
}

Nếu quyết định là “dừng lại”:

else {
    // 1. 保存本轮统计
    saveRollRecord(false);  // false表示正常结束,非止损
    
    // 2. 保留资金池金额
    // strategyCapital 保持当前值,等待下次机会
    
    // 3. 回到空仓状态
    resetPositionState();
    
    Log("⏳ 已平仓,等待新信号...");
}

Những điểm chính của quy trình này:

  • Hãy đưa ra phán đoán ngay lập tức sau mỗi hành động thu lợi nhuận, không được chậm trễ.
  • Các tiêu chí đánh giá mang tính khách quan (mối quan hệ giữa các đường trung bình động), không dựa trên suy đoán chủ quan.
  • Tiếp tục gia tăng vị thế của bạn; dừng lại và bảo toàn những gì đã đạt được.

3.5 Sức mạnh và chi phí của lãi kép

Hãy cùng trải nghiệm sức mạnh của lãi kép thông qua một nghiên cứu trường hợp hoàn chỉnh:

Những câu chuyện thành công:

初始资金:100 USDT
止盈比例:10%
杠杆:3倍

第1次:100 USDT → 盈利30 → 资金池130
第2次:130 USDT → 盈利39 → 资金池169
第3次:169 USDT → 盈利50.7 → 资金池219.7
第4次:219.7 USDT → 盈利65.9 → 资金池285.6
第5次:285.6 USDT → 盈利85.7 → 资金池371.3

连续滚5次,100变成371.3,增长271%!

Trường hợp thất bại:

第1次:100 USDT → 盈利30 → 资金池130
第2次:130 USDT → 盈利39 → 资金池169
第3次:169 USDT → 趋势反转 → 触发止损
止损比例5%,亏损:169 × 3 × 5% = 25.35 USDT
剩余资金:169 - 25.35 = 143.65 USDT

原本从100滚到169,一次止损后只剩143.65

Đây chính là con dao hai lưỡi của giao dịch chuyển đổi hợp đồng:

  • Khi thành công:Tăng trưởng theo cấp số nhân thật thú vị.
  • Khi nó thất bại:Sự sụt giảm nhanh chóng, hoặc thậm chí là thua lỗ.

IV. Câu hỏi 3: Khi nào nên dừng lại? — Lệnh cắt lỗ là tuyến phòng thủ cuối cùng.

Cơ chế ngăn chặn thiệt hại

4.1 Hai phương pháp thoát hiểm

Rút lui chủ động: Xu hướng suy yếu
Tình huống này đã được đề cập trong “Câu hỏi số Hai” - sau khi chốt lời, nếu xu hướng được xác định là không hỗ trợ tăng trưởng thêm, hãy chủ động chọn cách dừng lỗ. Đây là chiến lược thoát lệnh lý tưởng, rời khỏi thị trường với lợi nhuận.

Thoát lệnh thụ động: kích hoạt lệnh dừng lỗ
Đây là điều chúng ta sẽ tập trung vào từ bây giờ – khi thị trường diễn biến ngược chiều và giá chạm mức cắt lỗ, chúng ta buộc phải đóng các vị thế của mình.

4.2 Sự cần thiết của lệnh cắt lỗ

Nhiều người không thích lệnh cắt lỗ vì:

  • Lệnh cắt lỗ có nghĩa là thừa nhận sai lầm.
  • Lệnh cắt lỗ sẽ dẫn đến thua lỗ thực tế.
  • Đôi khi giá bật tăng trở lại sau khi lệnh cắt lỗ được đặt.

Tuy nhiên, trong chiến lược vị thế luân chuyển,Cắt lỗ là giới hạn tối thiểu để tồn tại.Hãy suy nghĩ về điều này:

如果没有止损:
第1次:100 → 滚到 169
第2次:169 → 趋势反转,不止损
价格持续下跌:169 → 150 → 120 → 80 → 50...
最终可能全亏,甚至爆仓
如果有止损:
第1次:100 → 滚到 169
第2次:169 → 趋势反转,触发止损
止损5%:亏损 25.35
剩余:143.65
虽然亏了,但保留了大部分资金
可以等待下一个机会

Bản chất của lệnh cắt lỗ:Hãy tận dụng những khoản lỗ nhỏ, chắc chắn để tránh những rủi ro lớn, không chắc chắn.

4.3 Triển khai mã lệnh cắt lỗ

// 检查止损
function checkStopLoss(currentPrice, position) {
    var totalDrawdown = 0;
    
    // 计算当前回撤
    if (currentDirection == "LONG") {
        totalDrawdown = (currentPrice - entryPrice) / entryPrice;
    } else {
        totalDrawdown = (entryPrice - currentPrice) / entryPrice;
    }
    
    // 判断是否触发止损
    if (totalDrawdown < -StopLossPercent) {
        Log("❌ 触发止损!回撤:", (totalDrawdown * 100).toFixed(2), "%");
        
        // 1. 取消止盈单
        if (takeProfitOrderId) {
            Log("取消止盈单:", takeProfitOrderId);
            exchange.CancelOrder(takeProfitOrderId);
            takeProfitOrderId = null;
            Sleep(500);
        }
        
        // 2. 市价平仓(循环重试直到成功)
        var profit = closePositionMarketWithRetry(currentPrice, position);
        
        // 3. 更新策略资金池
        strategyCapital += profit;  // profit是负数
        totalProfitRealized += profit;
        
        Log("止损亏损:", profit.toFixed(2), "U");
        Log("策略剩余资金:", strategyCapital.toFixed(2), "U");
        
        // 4. 记录本轮止损亏损
        currentRoundLoss = Math.abs(profit);
        Log("本轮止损亏损:", currentRoundLoss.toFixed(2), "U");
        
        // 5. 保存本轮滚仓记录(被止损中断)
        saveRollRecord(true);  // true表示止损结束
        
        // 6. 重置状态
        resetPositionState();
        
        // 7. 检查资金是否充足
        if (strategyCapital < 10) {
            Log("💥 策略资金不足10U,停止运行");
            throw "资金不足";
        }
        
        Log("⏳ 已止损,等待新信号...");
    }
}

4.4 Điều kiện kết thúc trò chơi

Bạn còn nhớ “Trò chơi phiêu lưu lý trí” mà chúng ta đã nói đến không? Trò chơi này có điều kiện kết thúc rõ ràng:

Điều kiện 1: Vốn điều lệ giảm xuống bằng không.

if (strategyCapital <= 0) {
    Log("💥 游戏结束:资金池已归零");
    Log("本次冒险失败,100 USDT全部亏光");
    throw "资金耗尽";
}

Điều kiện 2: Rút lui tự nguyện

if (strategyCapital >= 目标金额) {
    Log("🎉 达到目标金额,可以选择主动退出");
    Log("锁定利润,开始新一轮100 USDT的游戏");
}

Điều kiện 3: Đạt số lần quay tối đa

if (连续滚仓次数 >= 10次) {
    Log("⚠️ 达到最大滚仓次数,主动退出");
    Log("持续时间太长,风险累积,见好就收");
    saveRollRecord(false);
    resetPositionState();
}

4.5 Sự cân bằng giữa rủi ro và lợi nhuận

Cốt lõi của toàn bộ chiến lược vị thế luân chuyển nằm ở chỗ…Tìm kiếm sự cân bằng giữa rủi ro và lợi nhuận

Về phía doanh thu:

  • Tăng trưởng kép: Vốn tích lũy tăng lên sau mỗi lần chốt lời.
  • Nắm bắt xu hướng: Kiếm lợi nhuận ổn định trong các xu hướng tăng/giảm.
  • Không có giới hạn trên: Về mặt lý thuyết, nó có thể tăng vô hạn.

Mặt rủi ro:

  • Bảo vệ cắt lỗ: Mức lỗ tối đa là 5% tổng vốn trong một giao dịch.
  • Tách biệt quỹ: Mức lỗ tối đa 100 USDT
  • Phân tích xu hướng: Tránh đặt lệnh cắt lỗ thường xuyên trong thị trường biến động mạnh.

V. Kiểm thử ngược thực tế: Phân tích trường hợp TRUMP_USDT

TRUMP_USDTPhân tích kiểm định ngược về ngày niêm yết đầu tiên của Binance Futures (20/01/2025 đến 21/01/2025):

Kiểm định ngược đường cong vốn chủ sở hữu

Bảng thống kê cuộn chuột

Kết quả kiểm thử ngược cho thấy:

Điểm nổi bật:

  • Chiến lược này đã nắm bắt thành công những biến động mạnh mẽ trong những ngày đầu sau khi Trump IPO.
  • Thông qua nhiều lần chuyển đổi quỹ, nguồn vốn đã tăng trưởng nhanh chóng.
  • Cơ chế chốt lời giúp giữ vững lợi nhuận trong suốt xu hướng.

Mức độ rủi ro:

  • Khi xu hướng đảo chiều, lệnh cắt lỗ sẽ khiến một phần lợi nhuận bị mất đi.
  • Tín hiệu đột phá giả xuất hiện trên thị trường đầy biến động.
  • Rủi ro tập trung cao hơn khi sử dụng một loại tiền tệ duy nhất.

Dữ liệu chính:

  • Tổng số lần chuyển đổi: X lần
  • Số lần cược tối đa trong một vòng: X lần
  • Mức sụt giảm tối đa: X%
  • Tỷ suất lợi nhuận cuối cùng: X%

VI. Bản chất và những hạn chế của chiến lược

6.1 Chiến lược này đang mô phỏng điều gì?

Qua phân tích trên, chúng ta có thể thấy rõ ràng rằng chiến lược này về bản chất là một sự mô phỏng:

Hành vi giao dịch của một nhà đầu tư mạo hiểm lý trí:

  • Có các quy tắc vào lệnh rõ ràng (không phải giao dịch bốc đồng).
  • Đặt mục tiêu lợi nhuận (tránh lòng tham).
  • Hãy rèn luyện kỷ luật cắt lỗ (đừng giữ các vị thế đang thua lỗ).
  • Có khả năng đưa ra các quyết định về vị thế giao dịch liên tục (và tận dụng lợi nhuận).
  • Có những hạn chế về nguồn tài trợ (để kiểm soát rủi ro).

Nguyên tắc cốt lõi của nó là:

  1. Hãy dành ra một khoản vốn cố định (100 USDT) để thử nghiệm.
  2. Kiếm tiền bằng cách nắm bắt xu hướng.
  3. Sau khi kiếm được tiền, hãy sử dụng lợi nhuận để tiếp tục giao dịch (lợi nhuận kép).
  4. Nếu xu hướng suy yếu, hãy dừng lại ngay lập tức.
  5. Nếu phán quyết sai, hãy nhanh chóng chấp nhận thua lỗ.
  6. Cho đến khi số tiền trong quỹ cạn kiệt hoặc được chuyển sang số dư đủ lớn.

6.2 Hạn chế của chiến lược

Hạn chế 1: Phụ thuộc vào thị trường theo xu hướng
Chiến lược này hoạt động kém hiệu quả trong thị trường biến động vì:

  • Thường xuyên xuất hiện các đợt bùng phát giả.
  • Giá đã điều chỉnh giảm sau khi tôi chốt lời, vì vậy tôi không thể tiếp tục giữ vị thế.
  • Việc liên tục đặt lệnh cắt lỗ sẽ làm cạn kiệt nguồn vốn.

Hạn chế 2: Độ nhạy của tham số
Các thông số như mục tiêu lợi nhuận 10% và cắt lỗ 5% không phải là tối ưu:

  • Các loại tiền tệ khác nhau có mức độ biến động khác nhau.
  • Các điều kiện thị trường khác nhau đòi hỏi các thông số khác nhau.
  • Các thông số cố định rất khó thích ứng với mọi tình huống.

Hạn chế 3: Điểm kích nổ không thể dự đoán được
Như đã đề cập trước đó, việc sử dụng các chỉ báo kỹ thuật để tham gia thị trường về cơ bản là một canh bạc:

  • Bạn có thể bỏ lỡ những biến động lớn thực sự của thị trường.
  • Vào lệnh trong giai đoạn đột phá giả.
  • Không thể lên kế hoạch trước như những người trong ngành.

6.3 Các lĩnh vực cần cải thiện

Phương án 1: Lọc các loại tiền tệ dựa trên quy trình làm việc

  • Đừng chỉ chọn đại một loại tiền điện tử nào đó rồi bỏ đi.
  • Thay vào đó, quy trình này được sử dụng để lọc ra những loại tiền điện tử phổ biến và có tiềm năng cao trước tiên.
  • Ví dụ: sự gia tăng đột biến trong các cuộc thảo luận trên mạng xã hội, khối lượng giao dịch bất thường và dữ liệu hoạt động trên chuỗi khối.
  • Việc sử dụng chiến lược vị thế luân chuyển trên các loại tiền điện tử này sẽ mang lại tỷ lệ thành công cao hơn.

Phương án 2: Điều chỉnh thông số một cách linh hoạt

  • Điều chỉnh tỷ lệ chốt lời và cắt lỗ dựa trên biến động lịch sử của đồng tiền.
  • Đối với các loại tiền tệ có độ biến động cao, hãy mở rộng phạm vi cắt lỗ một cách thích hợp.
  • Đối với các loại tiền điện tử có độ biến động thấp, bạn có thể hạ thấp mục tiêu lợi nhuận của mình.

Phương án 3: Nhiều quỹ đầu tư hoạt động song song

  • Vấn đề không phải là việc đổi 100 USDT sang một loại tiền tệ duy nhất.
  • Thay vào đó, nó được chia thành năm phần, mỗi phần trị giá 20 USDT, và được chuyển đổi đồng thời sang năm loại tiền điện tử khác nhau.
  • Đa dạng hóa rủi ro và tăng khả năng “trúng số độc đắc”.

Phần kết luận

Thông qua việc suy luận từ ba câu hỏi cốt lõi, chúng ta đã chứng minh đầy đủ cách chuyển đổi ý tưởng giao dịch về việc gia hạn vị thế thành mã logic. Bản chất của quá trình này là:Thể hiện tư duy giao dịch của một nhà đầu tư chấp nhận rủi ro một cách lý trí bằng cách sử dụng các quy tắc và cấu trúc dữ liệu chính xác.

Lưu ý quan trọng:

Đây chỉ là mô phỏng chiến lược vị thế luân chuyển. Trên thực tế, vị thế luân chuyển là một chiến lược giao dịch đòi hỏi nhiều kinh nghiệm thị trường. Chiến lược này chỉ là một công cụ. Sau này, nó có thể được kết hợp với các quy trình làm việc để xác định các loại tiền điện tử phổ biến hoặc có tiềm năng bùng nổ. Sử dụng công cụ này sẽ mang lại cho chúng ta nhiều bất ngờ hơn.

Hãy nhớ rằng:

  • Mức thua lỗ tối đa là 100 USDT, và rủi ro này có thể kiểm soát được.
  • Nếu bạn may mắn nắm bắt được một xu hướng lớn, khoản đầu tư của bạn có thể tăng gấp nhiều lần, thậm chí hàng chục lần.
  • Nhưng thường thì, nó có thể bao gồm những khoản lãi và lỗ nhỏ, và việc thử nghiệm lặp đi lặp lại.
  • Đây là một trò chơi đòi hỏi sự kiên nhẫn và kỷ luật.

Không có chiến lược nào đảm bảo lợi nhuận.Việc giữ vững vị thế chỉ là một công cụ. Điều thực sự quyết định thành công hay thất bại là khả năng của bạn trong việc:

  • Xác định các loại tiền điện tử tiềm năng (sử dụng phương pháp lọc theo quy trình làm việc).
  • Hãy tuân thủ các lệnh cắt lỗ (đừng ngoan cố giữ lệnh).
  • Hãy đủ can đảm để điều chỉnh lại vị thế của mình khi một xu hướng lớn xuất hiện (nhưng đừng thoát lệnh quá sớm).
  • Hãy giữ bình tĩnh (đừng để cảm xúc chi phối bạn).

Chúc các bạn đều tìm được “vận may lớn” của riêng mình trên hành trình giao dịch định lượng!

Địa chỉ chính sách đầy đủ:**Mã nguồn chiến lược -> ** https://www.fmz.com/strategy/521864

Mã chiến lược hoàn chỉnh:

”`js /*backtest start: 2025-01-20 00:00:00 end: 2025-01-21 00:00:00 period: 1m basePeriod: 1m exchanges: [{“eid”:“Futures_Binance”,“currency”:“TRUMP_USDT”,“balance”:5000}] */

// ============================================ // 滚仓策略 - EMA5/EMA10 简化版 // 使用 CreateOrder 统一下单 // 持续检测订单状态 // 止盈后根据EMA关系决定是否滚仓 // 新增:滚仓统计功能(三个两行表格) // 修复:方向记录、亏损记录、入场价格记录 // 优化:市价平仓循环重试直到成功 // 优化:滚仓统计表格新增开始/结束时间 // ============================================

// ========== 策略参数(可调整)========== var Symbol = “TRUMP_USDT.swap”; // 交易币种 var InitialCapital = 100; // 策略初始资金 100U var Leverage = 3; // 杠杆倍数 var RollProfitPercent = 0.10; // 滚仓盈利系数(10% = 0.10) var StopLossPercent = 0.05; // 止损系数(10% = 0.10)

// EMA参数 var FastEMA = 5; var SlowEMA = 10;

// 全局变量 var strategyCapital = InitialCapital; var entryPrice = 0; var lastRollPrice = 0; var rollCount = 0; var totalProfitRealized = 0; var currentDirection = “”; var takeProfitOrderId = null; // 止盈单ID var amountPrecision = 0; // 数量精度 var pricePrecision = 2; // 价格精度 var ctVal = 1; // 合约面值

// ========== 滚仓统计变量 ========== var currentRoundRolls = 0; // 本轮滚仓次数(连续滚仓) var currentRoundStartTime = 0; // 本轮开始时间 var currentRoundDirection = “”; // 本轮方向 var currentRoundTotalProfit = 0; // 本轮累计盈利(每次止盈累加) var currentRoundLoss = 0; // 本轮亏损(止损时记录) var currentRoundEntryPrice = 0; // 本轮入场价格 var rollHistory = []; // 滚仓历史记录 var maxHistoryRecords = 10; // 保留最近10次滚仓记录

function main() { Log(“=== EMA滚仓策略启动(CreateOrder模式 + 滚仓统计)===”); Log(“交易币种:”, Symbol); Log(“━━━━━━━━━━━━━━━━━━━━”);

// 获取市场信息
var markets = exchange.GetMarkets();
if (!markets || !markets[Symbol]) {
    Log("❌ 错误:无法获取", Symbol, "的市场信息");
    return;
}

var marketInfo = markets[Symbol];
amountPrecision = marketInfo.AmountPrecision;
pricePrecision = marketInfo.PricePrecision || 2;
ctVal = marketInfo.CtVal;

Log("市场信息:");
Log("  - 数量精度:", amountPrecision);
Log("  - 价格精度:", pricePrecision);
Log("  - 合约面值:", ctVal);

var account = _C(exchange.GetAccount);
Log("账户总资金:", account.Balance.toFixed(2), "U");
Log("策略使用资金:", InitialCapital, "U");
Log("杠杆倍数:", Leverage, "倍");
Log("滚仓系数:", (RollProfitPercent * 100), "%");
Log("止损系数:", (StopLossPercent * 100), "%");
Log("━━━━━━━━━━━━━━━━━━━━");

if (account.Balance < InitialCapital) {
    Log("❌ 错误:账户余额不足");
    return;
}

exchange.SetContractType("swap");
exchange.SetMarginLevel(Leverage);

var lastBarTime = 0;

while (true) {

    var records = _C(exchange.GetRecords, PERIOD_M1);

    if (records.length < SlowEMA + 5) {
        Sleep(3000);
        continue;
    }

    var currentBarTime = records[records.length - 1].Time;
    if (currentBarTime == lastBarTime) {
        Sleep(1000);
        continue;
    }
    lastBarTime = currentBarTime;

    var ticker = _C(exchange.GetTicker);
    var currentPrice = ticker.Last;
    var account = _C(exchange.GetAccount);
    var position = _C(exchange.GetPositions); 

    // 计算EMA
    var emaFast = TA.EMA(records, FastEMA);
    var emaSlow = TA.EMA(records, SlowEMA);

    if (emaFast.length < 3 || emaSlow.length < 3) {
        Sleep(3000);
        continue;
    }

    var ema5_current = emaFast[emaFast.length - 1];
    var ema5_prev = emaFast[emaFast.length - 2];
    var ema10_current = emaSlow[emaSlow.length - 1];
    var ema10_prev = emaSlow[emaSlow.length - 2];

    var isBullTrend = ema5_current > ema10_current;
    var isBearTrend = ema5_current < ema10_current;

    var bullCross = ema5_prev <= ema10_prev && ema5_current > ema10_current;
    var bearCross = ema5_prev >= ema10_prev && ema5_current < ema10_current;

    if(takeProfitOrderId){
        checkTakeProfitOrder();
    }

    // ========== 持仓逻辑 ==========
    if (position.length > 0) {
        var pos = position[0];
        currentDirection = pos.Type == PD_LONG ? "LONG" : "SHORT";

        if (entryPrice == 0) {
            entryPrice = pos.Price;
            lastRollPrice = pos.Price;
        }

        // 检查止损
        checkStopLoss(currentPrice, pos);

    } else {
        // ========== 空仓:等待信号 ==========
        if (bullCross) {
            Log("📈 金叉信号 - 做多");
            openPosition("LONG", currentPrice);
        } else if (bearCross) {
            Log("📉 死叉信号 - 做空");
            openPosition("SHORT", currentPrice);
        }
    }

    showStatus(account, position, currentPrice, ema5_current, ema10_current, isBullTrend, currentBarTime);

    Sleep(1000);
}

}

// 开仓(持续检测订单状态) function openPosition(direction, price) { Log(“🚀 开仓”, direction == “LONG” ? “做多” : “做空”); Log(“使用资金:”, strategyCapital.toFixed(2), “U”);

var positionValue = strategyCapital * Leverage;
var amount = _N(positionValue / price / ctVal, amountPrecision);

Log("计算数量:", amount, "| 持仓价值:", positionValue.toFixed(2), "U");

if (amount <= 0) {
    Log("❌ 数量无效");
    return false;
}

// 使用 CreateOrder 市价开仓
var orderId = exchange.CreateOrder(Symbol, direction == "LONG" ? "buy" : "sell", -1, amount);

if (!orderId) {
    Log("❌ 下单失败");
    return false;
}

Log("订单ID:", orderId, "开始持续检测...");

// 持续检测订单状态,直到成交或超时
var maxWaitTime = 30000;  // 最多等待30秒
var startTime = Date.now();
var checkCount = 0;

while (Date.now() - startTime < maxWaitTime) {
    Sleep(500);
    checkCount++;

    var order = exchange.GetOrder(orderId);
    if (!order) {
        Log("❌ 无法获取订单信息");
        continue;
    }

    if (order.Status == 1) {
        // 订单已成交
        var avgPrice = order.AvgPrice;
        entryPrice = avgPrice;
        lastRollPrice = avgPrice;
        currentDirection = direction;

        // ========== 修改:无论是否第一次,都要初始化/更新统计数据 ==========
        if (currentRoundRolls == 0) {
            // 第一次开仓:初始化所有统计数据
            currentRoundStartTime = Date.now();
            currentRoundDirection = direction;
            currentRoundTotalProfit = 0;
            currentRoundLoss = 0;
            currentRoundEntryPrice = avgPrice;
            Log("🆕 开始新一轮交易统计");
            Log("  - 开始时间:", _D(currentRoundStartTime));
            Log("  - 方向:", direction == "LONG" ? "🟢 多头" : "🔴 空头");
            Log("  - 入场价格:", avgPrice.toFixed(pricePrecision));
        } else {
            // 滚仓时:更新方向(理论上应该相同,但为了健壮性还是更新)
            currentRoundDirection = direction;
            Log("🔄 滚仓操作 (第", currentRoundRolls, "次)");
            Log("  - 方向:", direction == "LONG" ? "🟢 多头" : "🔴 空头");
            Log("  - 入场价格:", avgPrice.toFixed(pricePrecision));
        }

        Log("✅ 开仓成功!");
        Log("  - 成交均价:", avgPrice.toFixed(pricePrecision));
        Log("  - 成交数量:", order.DealAmount);
        Log("  - 成交金额:", (order.DealAmount * avgPrice * ctVal).toFixed(2), "U");

        // 挂止盈单
        Sleep(1000);
        placeTakeProfitOrder(direction, avgPrice, order.DealAmount);

        return true;
    } else if (order.Status == 2) {
        // 订单已取消
        Log("❌ 订单已取消");
        return false;
    }
    // Status == 0 表示未成交,继续等待
}

// 超时未成交
Log("⚠️ 订单超时,尝试取消订单");
exchange.CancelOrder(orderId);
return false;

}

// 挂止盈单 function placeTakeProfitOrder(direction, entryPrice, amount) { var takeProfitPrice = 0;

if (direction == "LONG") {
    takeProfitPrice = _N(entryPrice * 1.1, pricePrecision);  // 多头止盈:+10%
} else {
    takeProfitPrice = _N(entryPrice * 0.9, pricePrecision);  // 空头止盈:-10%
}

Log("📌 挂止盈单");
Log("  - 入场价格:", entryPrice.toFixed(pricePrecision));
Log("  - 止盈价格:", takeProfitPrice);
Log("  - 数量:", amount);

// 使用 CreateOrder 挂限价止盈单
if (direction == "LONG") {
    takeProfitOrderId = exchange.CreateOrder(Symbol, "closebuy", takeProfitPrice, amount);
} else {
    takeProfitOrderId = exchange.CreateOrder(Symbol, "closesell", takeProfitPrice, amount);
}

if (takeProfitOrderId) {
    Log("✅ 止盈单已挂,订单ID:", takeProfitOrderId);
} else {
    Log("❌ 止盈单挂单失败");
}

}

// 检查止盈单状态 function checkTakeProfitOrder() {

if (!takeProfitOrderId) {
    return;
}

var order = exchange.GetOrder(takeProfitOrderId);
if (!order) {
    return;
}

if (order.Status == 1) {
    // 止盈单成交
    Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    Log("💰 止盈单成交!");
    Log("  - 成交价格:", order.AvgPrice.toFixed(pricePrecision));
    Log("  - 成交数量:", order.DealAmount);

    // 使用订单数据精确计算盈利
    var profit = 0;
    if (currentDirection == "LONG") {
        // 多头盈利 = (止盈价 - 入场价) * 数量 * 合约面值
        profit = (order.AvgPrice - entryPrice) * order.DealAmount * ctVal;
    } else {
        // 空头盈利 = (入场价 - 止盈价) * 数量 * 合约面值
        profit = (entryPrice - order.AvgPrice) * order.DealAmount * ctVal;
    }

    // 计算盈利率
    var profitRate = profit / strategyCapital;

    Log("📊 盈利统计:");
    Log("  - 入场价格:", entryPrice.toFixed(pricePrecision));
    Log("  - 止盈价格:", order.AvgPrice.toFixed(pricePrecision));
    Log("  - 本次盈利:", profit.toFixed(2), "U");
    Log("  - 盈利率:", (profitRate * 100).toFixed(2), "%");
    Log("  - 策略资金(盈利前):", strategyCapital.toFixed(2), "U");

    // 更新资金
    strategyCapital += profit;
    totalProfitRealized += profit;
    rollCount++;

    Log("  - 策略资金(盈利后):", strategyCapital.toFixed(2), "U");
    Log("  - 累计盈利:", totalProfitRealized.toFixed(2), "U");
    Log("  - 滚仓次数:", rollCount, "次");

    // ========== 累加本轮盈利 ==========
    currentRoundTotalProfit += profit;
    Log("  - 本轮累计盈利:", currentRoundTotalProfit.toFixed(2), "U");

    // 重置止盈单ID
    takeProfitOrderId = null;

    // 获取最新K线计算EMA
    Sleep(1000);
    var records = _C(exchange.GetRecords, PERIOD_M1);
    var emaFast = TA.EMA(records, FastEMA);
    var emaSlow = TA.EMA(records, SlowEMA);

    if (emaFast.length < 2 || emaSlow.length < 2) {
        Log("⚠️ EMA数据不足,无法判断是否滚仓");

        // 记录本轮滚仓结束(正常结束,之前有盈利)
        saveRollRecord(false);

        resetPositionState();
        Log("⏳ 等待新信号...");
        Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
        return;
    }

    var ema5_current = emaFast[emaFast.length - 1];
    var ema10_current = emaSlow[emaSlow.length - 1];

    Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    Log("📈 EMA滚仓判断:");
    Log("  - EMA5:", ema5_current.toFixed(pricePrecision));
    Log("  - EMA10:", ema10_current.toFixed(pricePrecision));
    Log("  - 原持仓方向:", currentDirection);

    var shouldRoll = false;

    if (currentDirection == "LONG") {
        // 多头止盈后,如果EMA5仍在EMA10上方,继续做多(滚仓)
        if (ema5_current > ema10_current) {
            shouldRoll = true;
            Log("  - 判断结果: ✅ EMA5 > EMA10,趋势延续");
            Log("  - 决策: 🔄 继续做多(滚仓)");
        } else {
            Log("  - 判断结果: ❌ EMA5 <= EMA10,趋势转弱");
            Log("  - 决策: ⏸️ 不滚仓,等待新信号");
        }
    } else if (currentDirection == "SHORT") {
        // 空头止盈后,如果EMA5仍在EMA10下方,继续做空(滚仓)
        if (ema5_current < ema10_current) {
            shouldRoll = true;
            Log("  - 判断结果: ✅ EMA5 < EMA10,趋势延续");
            Log("  - 决策: 🔄 继续做空(滚仓)");
        } else {
            Log("  - 判断结果: ❌ EMA5 >= EMA10,趋势转弱");
            Log("  - 决策: ⏸️ 不滚仓,等待新信号");
        }
    }

    Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");

    if (shouldRoll) {
        // ========== 滚仓:增加本轮滚仓次数 ==========
        currentRoundRolls++;
        Log("🔄 执行滚仓操作... (本轮第", currentRoundRolls, "次滚仓)");
        Sleep(1000);

        var ticker = _C(exchange.GetTicker);
        var newPrice = ticker.Last;

        if (openPosition(currentDirection, newPrice)) {
            Log("✅ 滚仓成功!");
        } else {
            Log("❌ 滚仓失败,等待新信号");
            // 记录本轮滚仓结束(滚仓失败,但之前有盈利)
            saveRollRecord(false);
            resetPositionState();
        }
    } else {
        // ========== 不滚仓:记录本轮滚仓结束 ==========
        saveRollRecord(false);
        resetPositionState();
        Log("⏳ 已平仓,等待新信号...");
    }

    Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
}

}

// ========== 保存滚仓记录 ========== function saveRollRecord(isStopLoss) { // 必须有开始时间才记录(防止异常情况) if (currentRoundStartTime == 0) { Log(“⚠️ 本轮未正确初始化,跳过记录”); currentRoundRolls = 0; currentRoundTotalProfit = 0; currentRoundLoss = 0; currentRoundDirection = “”; currentRoundEntryPrice = 0; return; }

var endTime = Date.now();
var duration = endTime - currentRoundStartTime;

// 计算总体盈利 = 累计盈利 - 亏损
var netProfit = currentRoundTotalProfit - currentRoundLoss;

var record = {
    direction: currentRoundDirection,      // 本轮方向
    roundRolls: currentRoundRolls,        // 本轮滚仓次数
    totalProfit: currentRoundTotalProfit, // 累计盈利(止盈累加)
    loss: currentRoundLoss,               // 亏损金额(止损)
    netProfit: netProfit,                 // 总体盈利
    duration: duration,                   // 持续时间(毫秒)
    isStopLoss: isStopLoss,              // 是否止损结束
    startTime: currentRoundStartTime,     // 开始时间
    endTime: endTime,                     // 结束时间
    entryPrice: currentRoundEntryPrice    // 入场价格
};

rollHistory.push(record);

// 只保留最近N条记录
if (rollHistory.length > maxHistoryRecords) {
    rollHistory.shift();
}

Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
Log("📝 保存滚仓记录:");
Log("  - 方向:", currentRoundDirection == "LONG" ? "🟢 多头" : "🔴 空头");
Log("  - 入场价格:", currentRoundEntryPrice.toFixed(pricePrecision));
Log("  - 开始时间:", _D(currentRoundStartTime));
Log("  - 结束时间:", _D(endTime));
Log("  - 持续时间:", formatDuration(duration));
Log("  - 本轮滚仓次数:", currentRoundRolls);
Log("  - 累计盈利:", currentRoundTotalProfit.toFixed(2), "U");
Log("  - 亏损金额:", currentRoundLoss.toFixed(2), "U");
Log("  - 总体盈利:", netProfit.toFixed(2), "U");
Log("  - 结束方式:", isStopLoss ? "❌ 止损" : "✅ 正常");
Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");

// 重置本轮统计数据
currentRoundRolls = 0;
currentRoundStartTime = 0;
currentRoundDirection = "";
currentRoundTotalProfit = 0;
currentRoundLoss = 0;
currentRoundEntryPrice = 0;

}

// 格式化时长 function formatDuration(ms) { var seconds = Math.floor(ms / 1000); var minutes = Math.floor(seconds / 60); var hours = Math.floor(minutes / 60); var days = Math.floor(hours / 24);

if (days > 0) {
    return days + "天" + (hours % 24) + "时" + (minutes % 60) + "分";
} else if (hours > 0) {
    return hours + "时" + (minutes % 60) + "分";
} else if (minutes > 0) {
    return minutes + "分" + (seconds % 60) + "秒";
} else {
    return seconds + "秒";
}

}

// 重置持仓状态函数 function resetPositionState() { entryPrice = 0; lastRollPrice = 0; currentDirection = “”; // 注意:不重置 rollCount、strategyCapital 和 currentRoundRolls }

// 检查止损 function checkStopLoss(currentPrice, position) { var totalDrawdown = 0;

if (currentDirection == "LONG") {
    totalDrawdown = (currentPrice - entryPrice) / entryPrice;
} else {
    totalDrawdown = (entryPrice - currentPrice) / entryPrice;
}

if (totalDrawdown < -StopLossPercent) {
    Log("❌ 触发止损!回撤:", (totalDrawdown * 100).toFixed(2), "%");

    // 取消止盈单
    if (takeProfitOrderId) {
        Log("取消止盈单:", takeProfitOrderId);