2
fokus pada
410
Pengikut

Permainan Pengembara: Pelaksanaan Kod dan Aplikasi Strategi Rollover

Dicipta dalam: 2025-12-19 17:06:01, dikemas kini pada: 2025-12-29 09:04:46
comments   0
hits   353

[TOC]

Permainan Pengembara: Pelaksanaan Kod dan Aplikasi Strategi Rollover

pengenalan

Dalam bidang perdagangan kuantitatif, strategi kedudukan bergolek merupakan topik yang menarik namun mencabar. Idea teras strategi ini adalah untuk mencapai pertumbuhan kompaun dengan melabur semula keuntungan yang direalisasikan dalam pasaran yang sedang trending. Artikel ini akan mengkaji cara menterjemahkan idea perdagangan ini ke dalam logik kod yang boleh dilaksanakan langkah demi langkah, dengan memberi tumpuan kepada perubahan minda dan bukannya butiran teknikal. Adalah penting untuk ambil perhatian bahawa walaupun strategi kedudukan bergolek menguatkan pulangan, ia juga menguatkan risiko; artikel ini adalah untuk tujuan pembelajaran dan perbincangan sahaja.


I. Analisis mendalam tentang logik keuntungan strategi kedudukan bergolek

1.1 Intipati Matematik bagi Rollover

Gambarajah guling balik

Logik keuntungan bagi strategi kedudukan bergolek pada asasnya adalahModel pertumbuhan majmukMari kita fahami ini menggunakan contoh yang dipermudahkan:

Dagangan tunggal tradisional (3 kenaikan 10% berturut-turut setiap satu):

  • Modal permulaan: 100 USDT, leveraj 3x
  • Peningkatan pasaran: (1+10%) × (1+10%) × (1+10%) - 1 = 33.1%
  • Keuntungan: 100 × 3 × 33.1% = 99.3 USDT
  • Harga akhir: 199.3 USDT

Dagangan rollover (tiga dagangan berturut-turut, setiap satu meningkat sebanyak 10%):

  • Kali pertama100 USDT → Keuntungan 30 USDT → Dana menjadi 130 USDT
    • Pengiraan: 100 × 3x leveraj × peningkatan 10% = 30
  • Kali ke-2130 USDT → Keuntungan 39 USDT → Dana menjadi 169 USDT
    • Pengiraan: 130 × 3x leveraj × peningkatan 10% = 39
  • ke-3169 USDT → Keuntungan 50.7 USDT → Dana meningkat kepada 219.7 USDT
    • Pengiraan: 169 × 3x leveraj × peningkatan 10% = 50.7

Keputusan perbandingan:

Dalam senario yang sama di mana pasaran meningkat sebanyak 10% tiga kali berturut-turut:

  • transaksi tunggalKeuntungan sebanyak 99.3 USDT
  • Dagangan rolloverKeuntungan sebanyak 119.7 USDT
  • Kelebihan faedah kompaun20.4 USDT (peningkatan kira-kira 20.5%)

Begitu juga, dengan tiga kenaikan 10% berturut-turut setiap kali, keuntungan untuk satu dagangan ialah 99.3 USDT, dan keuntungan untuk rolling over posisi ialah 119.7 USDT.Perbezaan ini adalah kuasa faedah kompaun.

Dinyatakan menggunakan formula matematik:

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

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

Ini mendedahkan intipati peralihan:Mengubah pertumbuhan linear kepada pertumbuhan eksponenWalau bagaimanapun, ini juga mendedahkan risiko:Satu pesanan stop-loss boleh menghapuskan semua keuntungan pengkompaunan sebelumnya.

1.2 Tiga Isu Teras Strategi Rollover

Sebelum kita mula menulis sebarang kod, kita perlu menjawab tiga soalan asas dari perspektif strategik:

Soalan 1: Bilakah ia bermula? (Entri pertama)
Ia adalah perlu untuk menentukan isyarat permulaan sesuatu trend.

Soalan 2: Bilakah perlu diteruskan? (Kedudukan guling tambahan)
Inilah teras posisi rolling over: bagaimana menentukan sama ada trend akan berterusan selepas mengambil keuntungan.

Soalan 3: Bilakah perlu berhenti? (Berhenti dan perhatikan)

  • Keluar Proaktif: Trend yang Semakin Melemah
  • Keluar pasif: mencetuskan stop loss

Tiga soalan ini menentukan rangka kerja keseluruhan strategi, dan kini kami akan menterjemahkannya ke dalam logik kod satu persatu.


II. Soalan 1: Bilakah hendak bermula? — Mencari titik perubahan untuk permulaan.

Isyarat masuk

2.1 Ideal dan Realiti Strategi Rollover

Mari kita fahami dahulu senario aplikasi ideal untuk strategi kedudukan bergolek.

Senario ideal:
Bayangkan jika anda boleh memasuki pasaran SHIB apabila ia mula meningkat dari $0.000001, atau menetapkan kedudukan sebelum altcoin tertentu mengalami lonjakan. Melalui rolling over yang berterusan, 100 USDT berpotensi menjadi 10,000 USDT atau lebih. Inilah impian utama strategi rolling over—Masuki pasaran sebelum mata wang kripto meletup dan raih pulangan sepuluh kali ganda atau seratus kali ganda.

Realiti pahit:
Masalahnya, bagaimana anda tahu mata wang kripto mana yang akan melonjak? Dan bilakah ia akan melonjak?

  • Jika anda pemilik projek atau orang dalam, anda mungkin mempunyai pengetahuan awal tentang berita positif.
  • Jika anda seorang pedagang tetap, anda hanya boleh membuat penilaian berdasarkan isyarat pasaran.

Bagi kebanyakan daripada kita, menangkap titik perubahan ini dengan tepat adalah…Secara terus terang, semuanya tentang nasib.Kita tidak boleh meramalkan masa depan; kita hanya boleh cuba meningkatkan kebarangkalian “menang besar” dengan menggunakan data sejarah dan penunjuk teknikal.

2.2 Dari Ideal kepada Realiti: Kemasukan Simulasi Berdasarkan Petunjuk Teknikal

Oleh kerana kita tidak dapat meramalkan mata wang kripto mana yang akan melonjak naik, apa yang boleh kita lakukan ialah:Tetapkan satu set peraturan kemasukan yang boleh dilaksanakan dan gunakan penunjuk teknikal untuk mensimulasikan isyarat “permulaan trend”.

Ia seperti memancing di lautan yang luas. Walaupun kita tidak tahu di mana ikan besar berada, kita boleh:

  • Perhatikan riak di permukaan air (turun naik harga).
  • Menganalisis arah aliran air (arah trend).
  • Pilih alat yang sesuai (penunjuk teknikal)

Apabila pelbagai isyarat bertemu, kita percaya trend mungkin akan bermula, jadi kita memasuki pasaran untuk mencubanya. Jika kita betul, kita mengikuti trend dan menggulingkan posisi kita untuk menjana wang; jika kita salah, kita mengurangkan kerugian kita dan keluar dari pasaran dengan segera.

2.3 Pelaksanaan Teknikal Isyarat Kemasukan

Memilih alat teknikal:
Kami menggunakan sistem purata bergerak dwi EMA (EMA5 dan EMA10) sebagai alat pengenalpastian trend. Sebab memilihnya adalah mudah:

  • Mudah, intuitif dan mudah untuk disahkan
  • Mampu bertindak balas dengan cepat terhadap perubahan harga
  • Parameter mengimbangi kepekaan dan kestabilan

Logik teras:
Dengan mengesan “palang emas” (palang EMA5 di atas EMA10) dan “palang maut” (palang EMA5 di bawah EMA10) bagi purata bergerak, titik pembalikan trend boleh dikenal pasti.

  • Salib emas → Isyarat beli
  • Salib kematian → Isyarat jualan singkat

Idea kod:

// 计算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);
}

Bahagian ini tidak akan membincangkan butiran tentang salib emas dan salib kematian; ini adalah konsep asas dalam perdagangan. Perkara utama ialah:Kita memerlukan isyarat kemasukan yang jelas dan boleh diukur untuk mencetuskan permulaan rollover.


III. Soalan 2: Bilakah perlu diteruskan? — Mekanisme teras faedah kompaun.

Mekanisme peralihan

3.1 Memahami intipati rollover: Permainan pengembara yang rasional

Strategi peralihan pada asasnya adalahPermainan pengembara yang rasionalMari kita fahami ini menggunakan senario yang lengkap:

Peraturan Permainan:

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

Kehebatan permainan ini terletak pada:

  • Risiko boleh diurus: kerugian maksimum ialah 100 USDT, yang tidak akan menjejaskan dana lain dalam akaun.
  • Keuntungan tanpa had: Jika trend sejajar, faedah kompaun boleh menggandakan modal anda dengan cepat.
  • Peraturan yang jelas untuk masuk dan keluar: peraturan yang jelas untuk mengambil keuntungan, menghentikan kerugian dan melancarkan posisi.

3.2 Reka Bentuk Kolam Modal: Kunci untuk Mencapai Faedah Kompaun

Ini merupakan konsep reka bentuk teras bagi strategi kedudukan bergolek.

Masalah dengan amalan tradisional:
Dengan mengandaikan akaun pertukaran anda mempunyai 1000 USDT:

  • Posisi pertama dibuka dengan 100 USDT.
  • Selepas membuat keuntungan sebanyak 30 USDT, baki akaun menjadi 1030 USDT.
  • Berapa banyak yang perlu saya gunakan untuk posisi pembukaan kedua? 100 atau 130?
  • Bagaimanakah kita boleh membezakan sama ada keuntungan datang daripada strategi kedudukan bergolek atau daripada operasi lain?

Penyelesaian pengumpulan dana:

// 创建一个虚拟的"策略资金池"
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(继续利滚利)

Kelebihan reka bentuk ini:

  • Pengasingan dana:Strategi ini hanya menggunakan 100 USDT yang ditentukan dan tidak menjejaskan dana lain dalam akaun.
  • Faedah kompaun automatik:Setiap keuntungan ditambah secara automatik ke dalam kumpulan modal, jadi jumlah yang lebih besar akan digunakan untuk posisi seterusnya.
  • Risiko boleh dikawal:Senario terburuk ialah kerugian 100 USDT, yang masih dalam jangkaan.
  • Penjejakan yang jelas:Ia dapat menentukan dengan tepat berapa banyak strategi itu beralih daripada 100 USDT.

3.3 Keputusan Rollover: Teruskan atau Berhenti Selepas Mengambil Keuntungan?

Ini adalah elemen teras strategi kedudukan bergolek:Selepas pesanan ambil untung dilaksanakan, kita perlu membuat keputusan penting – teruskan berdagang atau berhenti?

Senario membuat keputusan:

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

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

Bagaimana untuk memilih?

Keputusan ini tidak boleh berdasarkan “perasaan”; mesti ada piawaian yang jelas. Logik pertimbangan kami ialah:Adakah trend ini berterusan?

Kaedah penghakiman:
Pada masa pesanan ambil untung dilaksanakan, penunjuk teknikal terkini (purata bergerak EMA) dikira semula:

// 止盈单成交后,获取最新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 Proses Pelaksanaan Rollover

Jika keputusannya adalah “teruskan peralihan kedudukan”:

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();
    }
}

Jika keputusannya “berhenti”:

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

Perkara utama proses ini:

  • Buat penilaian serta-merta selepas setiap tindakan pengambilan untung, tanpa berlengah.
  • Kriteria penilaian adalah objektif (hubungan antara purata bergerak), tanpa spekulasi subjektif.
  • Teruskan meningkatkan kedudukan anda; berhenti dan kekalkan keuntungan anda.

3.5 Kuasa dan Kos Faedah Kompaun

Mari kita alami kuasa faedah kompaun melalui kajian kes yang lengkap:

Kisah kejayaan:

初始资金: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%!

Kes Kegagalan:

第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

Ini adalah pedang bermata dua dalam perdagangan rollover:

  • Setelah berjaya:Pertumbuhan eksponen adalah mengujakan.
  • Apabila ia gagal:Kemerosotan pantas, atau kerugian

IV. Soalan 3: Bilakah perlu berhenti? — Henti rugi ialah barisan pertahanan terakhir.

Pencegahan kerosakan

4.1 Dua kaedah keluar

Keluar Proaktif: Trend yang Semakin Melemah
Situasi ini telah dibincangkan dalam “Soalan Dua”—selepas mengambil keuntungan, jika trend ditentukan tidak menyokong keuntungan selanjutnya, pilih secara aktif untuk berhenti. Ini adalah strategi keluar yang ideal, meninggalkan pasaran dengan keuntungan.

Keluar pasif: mencetuskan stop loss
Inilah yang akan kita fokuskan sekarang – apabila pasaran bergerak menentang kita dan harga mencecah garisan henti rugi, kita terpaksa menutup posisi kita.

4.2 Keperluan stop loss

Ramai orang tidak menyukai pesanan stop-loss kerana:

  • Henti rugi bermaksud mengakui kesilapan.
  • Henti rugi akan mengakibatkan kerugian sebenar.
  • Kadangkala harga melantun semula selepas pesanan stop-loss diletakkan.

Walau bagaimanapun, dalam strategi kedudukan bergulir,Henti rugi adalah matlamat utama untuk terus hidup.Fikirkanlah:

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

Intipati henti rugi:Gunakan kerugian kecil yang pasti untuk mengelakkan risiko yang besar dan tidak menentu.

4.3 Pelaksanaan kod henti rugi

// 检查止损
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 Syarat-syarat untuk Penamatan Permainan

Ingat “Permainan Pengembara Rasional” yang telah kita bincangkan? Permainan ini mempunyai syarat penamat yang jelas:

Keadaan 1: Kumpulan modal dikurangkan kepada sifar.

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

Syarat 2: Pengeluaran secara sukarela

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

Syarat 3: Capai bilangan maksimum rollover

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

4.5 Keseimbangan antara risiko dan pulangan

Teras keseluruhan reka bentuk strategi kedudukan bergolek adalah dalamMencari keseimbangan antara risiko dan pulangan

Bahagian pendapatan:

  • Pertumbuhan kompaun: Kumpulan modal meningkat selepas setiap tindakan pengambilan untung.
  • Menangkap Trend: Mendapat keuntungan secara konsisten dalam aliran menaik/aliran menurun
  • Tiada had atas: Secara teorinya, ia boleh bergolek selama-lamanya.

Bahagian risiko:

  • Perlindungan henti rugi: Kerugian maksimum 5% daripada modal dalam satu transaksi.
  • Pengasingan dana: Kerugian maksimum 100 USDT
  • Analisis trend: Elakkan pesanan stop-loss yang kerap dalam pasaran yang tidak menentu.

V. Pengujian Semula Praktikal: Analisis Kes TRUMP_USDT

TRUMP_USDTAnalisis ujian tersokong hari pertama penyenaraian Binance Futures (20 Januari 2025 hingga 21 Januari 2025):

Keluk ekuiti ujian tersokong

Jadual Statistik Rollover

Keputusan ujian belakang menunjukkan bahawa:

Sorotan:

  • Strategi itu berjaya menangkap turun naik dramatik pada hari-hari awal Trump selepas IPOnya.
  • Melalui pelbagai peralihan, pertumbuhan dana yang pesat telah dicapai.
  • Mekanisme pengambilan untung berkesan mengunci keuntungan dalam trend.

Pendedahan risiko:

  • Apabila trend berbalik, pesanan stop-loss menyebabkan sebahagian keuntungan dikembalikan.
  • Isyarat penembusan palsu muncul dalam pasaran yang tidak menentu.
  • Risiko penumpuan lebih tinggi dengan mata wang tunggal

Data utama:

  • Jumlah bilangan rollover: X kali ganda
  • Peralihan pusingan tunggal maksimum: X kali ganda
  • Pengeluaran maksimum: X%
  • Kadar pulangan akhir: X%

VI. Sifat dan batasan strategi

6.1 Apakah yang disimulasikan oleh strategi ini?

Melalui analisis di atas, kita dapat melihat dengan jelas bahawa strategi ini pada asasnya adalah simulasi:

Tingkah laku perdagangan seorang pengembara yang rasional:

  • Terdapat peraturan kemasukan yang jelas (bukan perdagangan impulsif).
  • Tetapkan sasaran keuntungan (elakkan ketamakan).
  • Mempunyai disiplin stop-loss (jangan kekal pada posisi yang rugi).
  • Mempunyai keupayaan untuk membuat keputusan kedudukan bergulir (dan menggunakan keuntungan).
  • Terdapat sekatan pembiayaan (untuk mengawal risiko).

Logik terasnya ialah:

  1. Ketepikan sejumlah modal tetap (100 USDT) untuk mencubanya.
  2. Jana wang dengan mengikuti trend.
  3. Selepas menjana wang, gunakan keuntungan tersebut untuk meneruskan perdagangan (pengkompaunan keuntungan).
  4. Jika trend semakin lemah, hentikan serta-merta.
  5. Jika penilaian anda salah, kurangkan kerugian anda dengan cepat.
  6. Sehingga dana berkurangan atau diagihkan kepada jumlah yang memuaskan.

6.2 Had Strategi

Had 1: Pergantungan pada pasaran trend
Strategi ini menunjukkan prestasi yang buruk dalam pasaran yang tidak menentu kerana:

  • Jerawat palsu yang kerap
  • Harga menjejaki semula selepas saya mengambil keuntungan, jadi saya tidak dapat melonjakkan posisi tersebut.
  • Pesanan stop-loss berulang kali mengurangkan jumlah modal.

Had 2: Kepekaan parameter
Parameter seperti sasaran keuntungan 10% dan henti rugi 5% tidak optimum:

  • Mata wang yang berbeza mempunyai turun naik yang berbeza
  • Keadaan pasaran yang berbeza memerlukan parameter yang berbeza
  • Parameter tetap sukar untuk disesuaikan dengan semua situasi.

Had 3: Titik letupan yang tidak dapat diramalkan
Seperti yang dinyatakan sebelum ini, penggunaan penunjuk teknikal untuk memasuki pasaran pada asasnya adalah satu perjudian:

  • Anda mungkin terlepas pergerakan pasaran yang sebenar.
  • Masuk semasa penembusan palsu
  • Tidak dapat merancang lebih awal seperti orang dalam

6.3 Bidang untuk Penambahbaikan

Arahan 1: Tapis mata wang berdasarkan aliran kerja

  • Jangan hanya memilih mana-mana mata wang kripto dan pergi.
  • Sebaliknya, aliran kerja digunakan untuk menapis mata wang kripto yang popular dan berpotensi tinggi terlebih dahulu.
  • Contohnya: lonjakan perbincangan media sosial, jumlah transaksi yang tidak normal dan data dalam rantaian yang aktif.
  • Menggunakan strategi kedudukan bergulir pada mata wang kripto ini akan menghasilkan kadar kejayaan yang lebih tinggi.

Arah 2: Laraskan parameter secara dinamik

  • Laraskan nisbah pengambilan untung dan henti rugi berdasarkan turun naik mata wang dalam sejarah.
  • Bagi mata wang yang sangat tidak menentu, perluaskan julat stop-loss dengan sewajarnya.
  • Untuk mata wang kripto dengan turun naik yang rendah, anda boleh menurunkan sasaran keuntungan anda.

Arah 3: Pelbagai kumpulan dana beroperasi secara selari

  • Ia bukan tentang meletakkan 100 USDT dalam satu mata wang.
  • Sebaliknya, ia dibahagikan kepada lima jumlah 20 USDT, yang digulung secara serentak pada lima mata wang kripto yang berpotensi.
  • Pelbagaikan risiko dan tingkatkan kebarangkalian “menang besar”.

Kesimpulan

Melalui deduksi tiga soalan teras, kami telah menunjukkan sepenuhnya cara menterjemahkan idea perdagangan rolling over posisi ke dalam logik kod. Intipati proses ini ialah:Luahkan pemikiran perdagangan seorang pengambil risiko yang rasional menggunakan peraturan dan struktur data yang tepat.

Nota Penting:

Ini hanyalah simulasi strategi rolling position. Pada hakikatnya, rolling position adalah strategi perdagangan yang memerlukan banyak pengalaman pasaran. Strategi ini hanyalah alat. Kemudian, ia boleh digabungkan dengan aliran kerja untuk mengenal pasti mata wang kripto yang popular atau meletup. Menggunakan alat ini akan membawa kita lebih banyak kejutan.

Ingatlah:

  • Kerugian maksimum ialah 100 USDT, dan risikonya boleh diurus.
  • Jika anda cukup bernasib baik untuk mengikuti trend utama, pelaburan anda boleh berganda beberapa kali ganda atau berpuluh-puluh kali ganda.
  • Tetapi selalunya, ia mungkin melibatkan keuntungan dan kerugian kecil, dan ujian berulang.
  • Ini adalah permainan yang memerlukan kesabaran dan disiplin.

Tiada strategi yang menjamin keuntungan.Menggulingkan kedudukan hanyalah alat. Apa yang benar-benar menentukan kejayaan atau kegagalan adalah keupayaan anda untuk:

  • Kenal pasti mata wang kripto yang berpotensi (menggunakan penapisan aliran kerja).
  • Kekalkan pesanan stop-loss (jangan degil).
  • Beranilah untuk mengubah posisi anda apabila trend utama muncul (jangan keluar terlalu awal).
  • Kekal rasional (jangan biarkan emosi anda mengawal diri anda).

Semoga anda semua menemui “nasib baik” anda sendiri dalam perjalanan perdagangan kuantitatif anda!

Alamat polisi penuh:**Kod sumber strategi -> ** https://www.fmz.com/strategy/521864

Kod strategi lengkap:

”`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);
        exchange.CancelOrder(takeProfitOrderId);
        takeProfitOrderId = null;
        Sleep(500);
    }

    // ========== 市价平仓(循环重试直到成功) ==========
    var profit = closePositionMarketWithRetry(currentPrice, position);

    // 更新策略资金池
    strategyCapital += profit;
    totalProfitRealized += profit;

    Log("止损亏损:", profit.toFixed(2), "U");
    Log("策略剩余资金:", strategyCapital.toFixed(2), "U");
    Log("累计盈利:", totalProfitRealized.toFixed(2), "U");

    // ========== 记录本轮止损亏损 ==========
    currentRoundLoss = Math.abs(profit);  // 转为正数保存
    Log("本轮止损亏损:", currentRoundLoss.toFixed(2), "U");

    // ========== 记录本轮滚仓结束(被止损中断) ==========
    saveRollRecord(true);

    // 重置状态
    resetPositionState();

    if (strategyCapital < 10) {
        Log("💥 策略资金不足10U,停止运行");
        throw "资金不足";
    }

    Log("⏳ 已止损,等待新信号...");
}

}

// ========== 市价平仓(带重试机制,直到成功) ========== function closePositionMarketWithRetry(currentPrice, position) { Log(“🔴 市价平仓(循环重试模式)”);

var maxRetries = 10;  // 最多重试10次
var retryCount = 0;

while (retryCount < maxRetries) {
    retryCount++;
    Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    Log("🔄 第", retryCount, "次平仓尝试");

    var profit = closePositionMarket(currentPrice, position);

    // 如果返回值不为0,说明平仓成功
    if (profit !== 0) {
        Log("✅ 平仓成功!");
        Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
        return profit;
    }

    // 平仓失败,检查持仓是否还存在
    Sleep(2000);
    var newPosition = _C(exchange.GetPosition);

    if (newPosition.length == 0) {
        Log("⚠️ 持仓已不存在,可能已被其他途径平仓");
        Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
        return 0;
    }

    // 更新position和currentPrice
    position = newPosition[0];
    var ticker = _C(exchange.GetTicker);
    currentPrice = ticker.Last;

    Log("⚠️ 平仓失败,", (maxRetries - retryCount), "次重试机会剩余");
    Log("等待3秒后重试...");
    Sleep(3000);
}

// 所有重试都失败
Log("❌ 平仓失败!已达到最大重试次数");
Log("⚠️ 请手动检查持仓状态!");
Log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
return 0;

}

// 市价平仓(持续检测订单状态) function closePositionMarket(currentPrice, position) { Log(“📤 发起市价平仓订单”);

var pos = position;
var amount = pos.Amount;

if (pos.Type == PD_LONG) {
    exchange.SetDirection("closebuy");
} else {
    exchange.SetDirection("closesell");
}

// 市价平仓
var orderType = pos.Type == PD_LONG ? "closebuy" : "closesell";
var orderId = exchange.CreateOrder(Symbol, orderType, -1, amount);

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

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("❌ 无法获取订单信息(检测", checkCount, "次)");
        continue;
    }

    if (order.Status == 1) {
        // 平仓成功
        Log("✅ 订单成交,成交价:", order.AvgPrice.toFixed(pricePrecision));
        var profit = calculateProfit(pos, order.AvgPrice);
        Log("盈亏:", profit.toFixed(2), "U");
        return profit;
    } else if (order.Status == 2) {
        Log("❌ 平仓订单已被取消");
        return 0;
    }

    // Status == 0 表示未成交,继续等待
    if (checkCount % 10 == 0) {
        Log("⏳ 订单未成交,已检测", checkCount, "次...");
    }
}

// 超时,取消订单
Log("⚠️ 平仓订单超时(等待30秒未成交)");
Log("尝试取消订单:", orderId);

var cancelResult = exchange.CancelOrder(orderId);
if (cancelResult) {
    Log("✅ 订单已取消");
} else {
    Log("⚠️ 取消订单失败,订单可能已成交或已取消");
}

Sleep(1000);

// 再次检查订单状态(可能取消期间成交了)
var finalOrder = exchange.GetOrder(orderId);
if (finalOrder && finalOrder.Status == 1) {
    Log("✅ 订单在取消期间成交,成交价:", finalOrder.AvgPrice.toFixed(pricePrecision));
    var profit = calculateProfit(pos, finalOrder.AvgPrice);
    Log("盈亏:", profit.toFixed(2), "U");
    return profit;
}

return 0;

}

// �