2
fokus pada
410
Pengikut

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?

Dicipta dalam: 2025-12-25 14:35:55, dikemas kini pada: 2026-01-09 11:16:40
comments   0
hits   189

[TOC]

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?

📢 Perisai Berlapis

Artikel ini adalahSains Popular tentang Transformasi Wavelet untuk Perdagangan PraktikalKod ini merupakan versi pengajaran yang dipermudahkan (mengecualikan langkah-langkah kompleks seperti penguraian berbilang peringkat, penyahbisingan ambang dan pembinaan semula transformasi songsang bagi wavelet piawai), hanya mengekalkan idea teras:Gunakan pekali wavelet untuk melakukan pelicinan berbilang skala pada harga bagi mendapatkan maklumat trend.Sesuai untuk pembangunan strategi dan pengesahan pantas, tetapi bukan untuk penyelidikan akademik atau penerbitan kertas kerja.


I. Pengenalan: Membongkar “Guru Zhihu” (Pakar)

Mereka yang kerap melayari topik kewangan dan kuantitatif di Zhihu pasti pernah melihat senario ini:

Sesetengah “pakar” terus berkata:

  • Pengurangan hingar transformasi gelombang
  • Tempoh pengekstrakan transformasi Fourier
  • Pelicinan Laplace membuang outlier.

Dia meninggalkan semua orang tergamam, seolah-olah dia telah menguasai senjata nuklear dalam perdagangan kuantitatif.

Tapi awak nak dia tunjukkan kod tu pada awak?
“Ini… rahsia perdagangan, dan saya tidak boleh mendedahkannya.”

Minta dia jelaskan prinsip tersebut.
“Ini… melibatkan matematik lanjutan, awak takkan faham walaupun saya terangkan kepada awak.”

Hari ini, kita akan meneroka topik yang sering disebut oleh “pakar Zhihu” ini, memperkenalkan aplikasi praktikal transformasi wavelet dalam pasaran kewangan, dan membantu semua orang membangunkan pemahaman yang betul tentang teknologi ini.


II. Apakah sebenarnya transformasi gelombang kecil?

Penjelasan mudah

Bayangkan anda sedang mendengar lagu, tetapi terdapat bunyi latar belakang dalam rakaman itu:

Rakaman asal = suara manusia + bunyi latar belakang + statik

Transformasi gelombang adalah sepertiPenapis Pintar

  • Peliharalah suara
  • Tapis hingar
  • Ia juga boleh memberitahu anda bahagian mana yang merupakan korus dan bahagian mana yang merupakan rangkap.

Beralih ke pasaran kewangan:

Harga Asal = Trend Sebenar + Turun Naik Jangka Pendek + Bunyi Rawak

Transformasi gelombang boleh membantu anda:

  • Mengekstrak trend sebenar(Hala tuju jangka panjang)
  • Menapis turun naik jangka pendek(Naik turun naik intraday)
  • Mengenal pasti titik infleksi utama(Pembalikan Trend)

Konsep teras: Penguraian fungsi asas

Intipati transformasi gelombang kecil ialahUraikan isyarat asal menggunakan set “fungsi asas” tertentu (wavelet).

Bayangkan anda ingin menggambarkan penampilan seseorang:

  • Kaedah tradisional: menerangkan piksel demi piksel, yang sangat membosankan.
  • Kaedah gelombang kecil: menggunakan faktor seperti “saiz mata, ketinggian hidung dan kontur muka”ciriUntuk menggabungkan penerangan

Dalam harga kewangan:

Siri harga asal = Fungsi asas 1 × Pemberat 1 + Fungsi asas 2 × Pemberat 2 + … + Hingar

Fungsi asas ialah “templat” yang sepadan dengan pekali wavelet.Jenis wavelet yang berbeza (Haar, Daubechies, Mexican Hat, dll.) menggunakan templat yang berbeza, sama seperti menggunakan “pengekstrak ciri” yang berbeza untuk menguraikan harga.

Penapis: Penapis dalam domain frekuensi

Transformasi gelombang pada asasnya adalah…Bank penapis berbilang skala:

Penapis frekuensi tinggi → Menangkap turun naik pantas (bunyi harian, turun naik tahap tik) Penapis frekuensi pertengahan → Menangkap trend jangka sederhana (jalur antara beberapa jam hingga beberapa hari). Penapis frekuensi rendah → Tangkap trend jangka panjang (trend mingguan dan bulanan).

Mengapa ia dipanggil “gelombang kecil”?

  • Kegunaan transformasi Fourier tradisionalGelombang sinus yang panjang tanpa batasSeperti pembaris yang panjangnya tidak terhingga
  • Transformasi gelombang digunakanGelombang “kecil” sepanjang terhinggaSeperti satu set pembaris dengan panjang yang berbeza

Masalah dengan penggunaan gelombang sinus untuk menganalisis harga kewangan: Gelombang sinus mengandaikan bahawa isyarat berulang secara berkala, tetapi pasaran kewangan tidak! BTC mungkin meningkat 10% hari ini dan jatuh 8% esok, tanpa sebarang kitaran.

Kelebihan wavelet:Analisis penyetempatanIa boleh memberitahu anda “trend harga terutamanya meningkat antara jam 3 petang dan 5 petang pada 20 Disember 2025”, dan bukannya kesimpulan umum seperti “keseluruhan pasaran berubah-ubah”.

Pembinaan Semula: Daripada Penguraian kepada Pembinaan Semula

Transformasi gelombang ialahBoleh diterbalikkanIni sangat penting!

Harga asal —> Penguraian gelombang —> Komponen trend + Komponen volatiliti + Komponen hingar Komponen trend + komponen turun naik + komponen hingar —> pembinaan semula wavelet —> harga asal

Proses pemfaktoran semulaIa adalah untuk menguraikan pelbagai komponen.Gabungkan kembali secara selektif

  • Komponen trend =[99800, 99850, 99900, 99950, …] # Apa yang kita mahukan
  • Komponen turun naik =[+200, -150, +180, -120, …] # Mungkin berguna
  • Komponen hingar =[±10, ±15, ±8, ±12, …] # Buang!

Hanya gunakan komponen trend semasa pembinaan semula

Selepas penguraian, perkara berikut diperolehi

  • Harga Dibina Semula = Komponen Trend + Komponen Volatiliti Separa

Dalam transaksi sebenar, kita biasanyaBina semula hanya bahagian frekuensi rendah(Trend) Komponen frekuensi tinggi (hingar) dibuang terus. Inilah prinsip “pengurangan hingar” gelombang kecil.

Prinsip Matematik (Versi Ringkas)

Mari kita langkau formula kamiran yang kompleks dan jelaskannya dalam istilah awam:

Transformasi gelombang = purata berwajaran siri harga menggunakan satu set “pekali gelombang”

Formula asas:

Harga yang meratakan[i] = Σ(harga asal)[i-j] × pekali gelombang kecil[j]) / Σ(pekali gelombang)[j])

Perspektif penapis

Harga asal ditapis melalui penapis wavelet → komponen frekuensi berbeza “dipilih”.

Kuncinya ialahPemilihan pekali wavelet

  • Wavelet berbeza = ciri penapis berbeza = tindak balas frekuensi berbeza
  • Tahap berbeza = skala masa berbeza = kitaran trend berbeza

Contohnya

Dengan mengandaikan anda menggunakan wavelet Daubechies 4, pekalinya ialah[0.483, 0.837, 0.224, -0.129]:

Set pekali ini mentakrifkan penapis:

  • Pekali positif (0.483, 0.837, 0.224) → Kekalkan harga untuk kedudukan ini.
  • Pekali negatif (-0.129) → Menyekat pergerakan harga terdahulu
  • Pemberat pekali → menentukan sumbangan setiap harga.

Transformasi wavelet selesai apabila anda “meluncurkan” penapis ini merentasi keseluruhan siri harga. Setiap slaid melibatkan pengiraan.Purata wajaran harga dalam tempoh semasaPemberatnya ialah pekali wavelet.

Mengapa ia boleh “menguraikan” isyarat?

Kerana ia boleh dibuktikan secara matematik bahawa:Sebarang isyarat boleh diwakili sebagai gabungan linear bagi fungsi asas wavelet.Sama seperti mana-mana warna boleh dicipta dengan mencampurkan tiga warna utama RGB, sebarang siri harga boleh diperoleh dengan menggabungkan fungsi asas wavelet. Jenis wavelet yang berbeza menyediakan “perpustakaan fungsi asas” yang berbeza, sesuai untuk pelbagai jenis analisis isyarat.


III. Percubaan Ini: Aplikasi Praktikal 7 Transformasi Gelombang

Pendekatan Aplikasi: Penyederhanaan daripada Teori kepada Amalan

Dalam buku teks pemprosesan isyarat, transformasi gelombang biasanya melibatkan…Penguraian berbilang peringkat, pembinaan semula dan penyahbisingan ambangLangkah-langkah:

Aliran kerja analisis wavelet yang lengkap:

  1. Penguraian berbilang skala → menghasilkan pekali penghampiran dan pekali terperinci.
  2. Ambang → Ambang lembut/keras untuk pekali terperinci bagi mengurangkan hingar
  3. Pembinaan semula transformasi songsang → memulihkan pekali yang diproses kepada isyarat
  4. Peluasan sempadan → Mengendalikan kesan sempadan isyarat
  5. Normalisasi tenaga → memastikan penjimatan tenaga sebelum dan selepas transformasi

TetapiAplikasi praktikal transaksi kewanganDi China, kita tidak memerlukannya menjadi begitu rumit. Kerana:

1. Dagangan hanya memerlukan arah trend; pembinaan semula yang sempurna tidak diperlukan.

Penyelidikan akademik mungkin memerlukan ralat pembinaan semula kurang daripada 0.01%, tetapi dalam perdagangan, ia mencukupi untuk menentukan sama ada harga akan “naik atau turun.” Walaupun pembinaan semula mempunyai ralat 5%, strategi tersebut masih boleh menguntungkan selagi arah trend betul.

2. Keperluan masa nyata memudahkan pengiraan.

Penguraian wavelet yang lengkap memerlukan pengiraan rekursif berbilang lapisan pekali, yang boleh menyebabkan kependaman dalam perdagangan frekuensi tinggi. Sebaliknya, konvolusi langsung boleh diselesaikan dalam milisaat, memenuhi keperluan perdagangan langsung.

3. Ciri-ciri Khas Isyarat Kewangan

Harga kewangan bukanlah isyarat yang stabil dan tidak menunjukkan kitaran yang ketat. Penguraian frekuensi yang kompleks tidak begitu bermakna di sini; pengekstrakan trend mudah adalah lebih praktikal.

Strategi penyederhanaan ini

Oleh itu, artikel iniMengekstrak intipati transformasi waveletMemberi tumpuan kepada aspek pasaran kewangan yang paling praktikal:

Penyederhanaan Teras 1: Gunakan hanya pekali anggaran (trend frekuensi rendah)

Penguraian wavelet tradisional → pekali penghampiran + pekali perincian (berbilang lapisan) Aplikasi ini: Hanya mengekalkan pekali anggaran → mendapatkan trend terlicin secara langsung.

Penyederhanaan Teras 2: Konvolusi Langsung, tanpa Penyahbisingan Ambang

Penguraian wavelet tradisional → ambang pekali terperinci → pembinaan semula Aplikasi ini: Konvolusi langsung → untuk mendapatkan harga yang terlicin

Penyederhanaan Teras 3: Abaikan Pemprosesan Sempadan

Wavelet tradisional memerlukan pemprosesan seperti pemanjangan simetri dan pemanjangan sempadan isyarat secara berkala. Aplikasi ini hanya tertumpu pada bahagian tengah; ralat sempadan boleh diterima.

Kaedah pelaksanaan: Konvolusi penapis

def convolve(src, coeffs, step):
    """
    核心算法:用小波系数对价格序列做加权平均
    
    src: 价格序列 [100000, 101000, 99000, ...]
    coeffs: 小波系数 [0.483, 0.837, 0.224, -0.129]
    step: 采样步长(用于多层级)
    """
    sum_val = 0.0   # 加权和
    sum_w = 0.0     # 权重和
    
    for i, weight in enumerate(coeffs):
        idx = i * step
        if idx < len(src):
            sum_val += src[idx] * weight
            sum_w += weight
    
    return sum_val / sum_w  # 归一化

Fungsi ini adalah…Teras penapis wavelet

  • Bagi setiap candlestick, ia melihat kembali N candlestick (N = bilangan pekali wavelet).
  • Kira purata berwajaran menggunakan pekali wavelet sebagai pemberat.
  • Dengan melaraskanstepParameter membolehkan pelicinan berbilang peringkat (Tahap 1/2/3…).

Mengapakah penyederhanaan ini munasabah?

Kerana keperluan penting transaksi adalah:Mencari Trend dalam KebisinganPekali penghampiran transformasi gelombang kecil itu sendiri merupakan “penapis laluan rendah” untuk isyarat, memelihara komponen trend frekuensi rendah, yang sememangnya apa yang kita perlukan.

Walaupun analisis wavelet yang lengkap lebih tepat, dalam perdagangan kewangan:

  • Keuntungan datang dari arah trendIa tidak datang daripada ketepatan pembinaan semula.
  • Kaedah yang lebih mudah adalah lebih mantapModel kompleks terdedah kepada kesesuaian berlebihan
  • Kelajuan pengiraan lebih pentingDalam perdagangan sebenar, setiap milisaat adalah wang.

Pemerolehan Data: Kemudahan Platform FMZ

gunaEnjin pengujian semula tempatan bagi platform Pengkuantitian Pencipta (FMZ)Ia sangat mudah untuk mendapatkan data!

'''backtest
start: 2025-12-17 00:00:00
end: 2025-12-23 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","fee":[0,0]}]
'''
from fmz import *

task = VCtx(__doc__)

def main():
    exchange.SetCurrency("BTC_USDT")
    exchange.SetContractType("swap")
    
    records = exchange.GetRecords(PERIOD_H1, 500)
    return records

records = main()

Tiada penyepaduan API yang kompleks atau pembersihan data diperlukan; data candlestick piawai boleh diperoleh secara langsung. Ini membolehkan kami mengesahkan kesan sebenar tujuh jenis wavelet dengan cepat, daripada terperangkap dalam pemprosesan data.

Sasaran ujian

Dengan membandingkan prestasi tujuh jenis wavelet biasa (Haar, Daubechies 4, Symlet 4, Biorthogonal 3.3, Mexican Hat, Morlet dan Discrete Meyer) pada harga mata wang kripto, demonstrasi visual berikut disediakan:

  • Perbezaan dalam keamatan pelicinan antara wavelet yang berbeza
  • Variasi kesan pada tahap berbeza bagi wavelet yang sama
  • Wavelet manakah yang sesuai untuk dagangan jangka pendek, dan yang manakah sesuai untuk mengikuti trend?

Tumpuannya bukan pada ketelitian terbitan matematik, tetapi pada perbandingan visual hasil praktikal.Ini membantu pedagang mengembangkan pemahaman intuitif dan memilih jenis wavelet yang sesuai dengan strategi mereka.


IV. Penjelasan Terperinci tentang 7 Jenis Wavelet

1. Haar wavelet - purata paling mudah

Wavelet Haar ialah jenis wavelet yang paling asas, dengan hanya dua pekali:[0.5, 0.5]Pada asasnya, ia adalah purata mudah bagi dua harga bersebelahan.

Kod teras:

coeffs = [0.5, 0.5]

# 对价格序列 [100000, 101000, 99000, 102000, 98000] 处理
def smooth(prices, i):
    return (prices[i] * 0.5 + prices[i-1] * 0.5) / 1.0

# 结果:[100000, 100500, 100000, 100500, 100000]

Seperti yang anda lihat, harga yang pada asalnya turun naik secara liar (dari 99,000 hingga 102,000) menjadi agak stabil selepas pemprosesan Haar. Ini adalah kesan “denoising” wavelet - melicinkan turun naik jangka pendek yang ganas, membolehkan anda melihat trend harga yang lebih lancar.

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?


2. Daubechies 4 - Biasa Digunakan dalam Projek Kejuruteraan

Daubechies 4 (db4 untuk pendek kata) ialah salah satu wavelet yang paling biasa digunakan dalam kejuruteraan. Pekalinya ialah:[0.483, 0.837, 0.224, -0.129]Perhatikan bahawa pekali terakhir ialah…nombor negatifItulah yang menjadikannya unik.

Kod teras:

coeffs = [0.483, 0.837, 0.224, -0.129]

# 处理第i个价格点
def smooth(prices, i):
    weighted_sum = (prices[i]   * 0.483 +    # 当前价格
                   prices[i-1] * 0.837 +     # 前1根,权重最大!
                   prices[i-2] * 0.224 +     # 前2根
                   prices[i-3] * (-0.129))   # 前3根,负权重
    
    weight_sum = 0.483 + 0.837 + 0.224 + (-0.129)  # = 1.415
    return weighted_sum / weight_sum

# 示例:smooth([100000, 101000, 99000, 102000], 3) ≈ 100251

Ciri-ciri Utama:Berat candlestick sebelumnya (0.837) adalah lebih besar daripada harga semasa (0.483)! Ini bermakna db4 lebih menekankan “harga yang baru sahaja berlaku”, dan pekali berat negatif akan mempunyai kesan “pengimbangan” pada harga sebelumnya, seterusnya meningkatkan kelancaran.

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?


3. Symlet 4 - Versi Simetri yang Dipertingkatkan

Symlet 4 ialah versi Daubechies yang dipertingkatkan, bertujuan untuk simetri yang lebih baik. Pekali:[-0.076, -0.030, 0.498, 0.804, 0.298, -0.099, -0.013, 0.032]

Kod teras:

coeffs = [-0.076, -0.030, 0.498, 0.804, 0.298, -0.099, -0.013, 0.032]

# 向前看8根K线
def smooth(prices, i):
    weighted_sum = sum(prices[i-j] * coeffs[j] for j in range(8))
    weight_sum = sum(coeffs)
    return weighted_sum / weight_sum

# 平滑效果比Haar和db4都强,但反应速度更慢

Ciri-ciri Utama:Panjang tetingkap 8 candlestick membolehkan “memori” harga yang lebih lama. Pembalikan trend sebenar mungkin tidak dapat dilihat pada lengkungan yang lancar sehingga selepas 8 candlestick berlalu.

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?


4. Biortogonal 3.3 - Simetri Sempurna

Biorthogonal 3.3 (disingkatkan sebagai bior3.3) ialah wavelet simetri sempurna dengan pekali:[-0.066, 0.283, 0.637, 0.283, -0.066]

Kod teras:

coeffs = [-0.066, 0.283, 0.637, 0.283, -0.066]
#           ↑              中心↑              ↑
#         完全对称的两端

# 处理中间价格点
def smooth(prices, i):
    # 实际应用:只向前看,不使用未来数据
    weighted_sum = (prices[i-4] * (-0.066) +   # 前4根
                   prices[i-3] * 0.283 +       # 前3根
                   prices[i-2] * 0.637 +       # 前2根,权重最大
                   prices[i-1] * 0.283 +       # 前1根
                   prices[i]   * (-0.066))     # 当前
    
    weight_sum = sum(coeffs)  # = 1.071
    return weighted_sum / weight_sum

Ciri-ciri Utama:Simetri memastikan tiada “herotan fasa” - lengkung yang licin tidak akan beralih ke kiri atau kanan secara tidak dapat dijelaskan.

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?


5. Topi Mexico - Pemburu Titik Pemulihan

Pekali Topi Mexico (juga dikenali sebagai wavelet Ricker):[-0.1, 0.0, 0.4, 0.8, 0.4, 0.0, -0.1]Ia berbentuk seperti sombrero Mexico.

Kod teras:

coeffs = [-0.1, 0.0, 0.4, 0.8, 0.4, 0.0, -0.1]
#         负值  零  正值  最大  正值  零  负值
#         ↓                            ↓
#       "惩罚"两端,增强拐点检测能力

def smooth(prices, i):
    weighted_sum = (prices[i-6] * (-0.1) +     # 左3,负权重
                   prices[i-5] * 0.0 +         # 左2
                   prices[i-4] * 0.4 +         # 左1
                   prices[i-3]   * 0.8 +         # 中心,权重最大
                   prices[i-2] * 0.4 +         # 右1
                   prices[i-1] * 0.0 +         # 右2
                   prices[i] * (-0.1))       # 右3,负权重
    
    weight_sum = sum(coeffs)
    return weighted_sum / weight_sum

Ciri-ciri Utama:Strukturnya yang “besar di tengah, negatif di kedua-dua hujung” menjadikannya sangat baik dalam pengesanan.titik lengkungan- Detik kritikal apabila harga berbalik daripada trend menaik kepada trend menurun (atau sebaliknya). Pekali pemberat negatif “menghukum” harga yang jauh, dengan cepat menangkap perubahan trend.

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?


6. Morlet - Raja Pelicinan Gaussian

Wavelet Morlet adalah berdasarkan taburan Gaussian (normal), dengan pekali:[0.0625, 0.25, 0.375, 0.25, 0.0625]

Kod teras:

coeffs = [0.0625, 0.25, 0.375, 0.25, 0.0625]
#          ↓      ↓      ↓中心   ↓      ↓
#        远端   近端   最高    近端   远端
#         完美的高斯钟形曲线

def smooth(prices, i):
    weighted_sum = (prices[i-4] * 0.0625 +     # 左2,6.25%
                   prices[i-3] * 0.25 +        # 左1,25%
                   prices[i-2]   * 0.375 +       # 中心,37.5%
                   prices[i-1] * 0.25 +        # 右1,25%
                   prices[i] * 0.0625)       # 右2,6.25%
    
    # 权重和正好 = 1.0,无需除法
    return weighted_sum

Ciri-ciri Utama:Gelombang yang paling “lembut”, ia tidak mempunyai pemberat negatif, dan semua harga dimasukkan secara perlahan ke dalam pengiraan. Lengkung yang terhasil sangat lancar, tetapi kosnya adalah tindak balas yang perlahan – perubahan harga secara tiba-tiba mungkin tidak dapat dilihat sehingga beberapa candlestick kemudian.

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?


7. Meyer Diskret - Pelicinan Terbaik

Wavelet Meyer Diskret ialah wavelet yang paling kompleks, dengan pekali:[-0.015, -0.025, 0.0, 0.28, 0.52, 0.28, 0.0, -0.025, -0.015]

Kod teras:

coeffs = [-0.015, -0.025, 0.0, 0.28, 0.52, 0.28, 0.0, -0.025, -0.015]
#           ↑       ↑            ↑    ↑中心↑   ↑            ↑       ↑
#                        完全对称,中心权重超过50%

def smooth(prices, i):
    # 向前看9根K线
    weighted_sum = sum(prices[i-j] * coeffs[j] for j in range(9))
    weight_sum = sum(coeffs)  # = 1.0
    return weighted_sum

# 注意:第4根之前的K线权重是0.52,超过50%!
# 实际上在告诉你"4根K线之前的中期趋势"

Ciri-ciri Utama:Ia mempunyai pekali paling banyak (9), data sejarah terpanjang, dan kesan pelicinan paling kuat. Ia sesuai untuk mengekstrak “trend mingguan”, tetapi terdapat kelewatan yang besar - walaupun harga telah jatuh sebanyak 10%, lengkungnya mungkin masih menunjukkan “terus meningkat”.

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?


5. Mengapa terdapat perbezaan dalam kesan pelicinan?

Selepas mengkaji tujuh jenis wavelet, anda sepatutnya perasan satu corak:

Lebih banyak pekali = lihat selanjutnya = pelicinan yang lebih kuat = kependaman yang lebih besar

Haar (2 pekali) → Hanya lihat pada 1 bar → Hampir tidak lancar Daubechies 4 (4 keping) → Lihat 3 sebelum → Sedikit licin Topi Mexico (7) → Lihat 6 sebelum → Pelicinan sederhana Diskret Meyer (9) → Sebelum melihat 8 bar → Pelicinan berat

Kesan pemberat negatif adalah untuk meningkatkan kepekaan dan memudahkan pengesanan perubahan.

Haar/Morlet (tiada pemberat negatif) → Lembut dan licin, tidak sensitif Topi Mexico (negatif di kedua-dua hujung) → Sensitif kepada titik infleksi Daubechies 4 (negatif) → Sensitif terhadap perubahan trend

Peranan simetri = tiada herotan = mengekalkan bentuk asal

Asimetri (Daubechies) → Mungkin beralih ke kiri/kanan Simetri (Biortogonal/Meyer) → Mengekalkan kedudukan tengah


VI. Kesan Tahap Pelicinan

Transformasi gelombang boleh digunakan secara rekursif, seperti anak patung bersarang. Aplikasi pertama dipanggil Tahap 1, menggunakannya sekali lagi pada hasil Tahap 1 dipanggil Tahap 2, dan begitulah seterusnya.

Skala masa yang dilihat pada tahap yang berbeza:

Dengan mengandaikan kita menggunakan carta candlestick 1 jam untuk perdagangan BTC:

Tahap 1 → Perhatikan turun naik jangka pendek dalam tempoh 2-4 jam Aras 2 → Perhatikan trend dalam tempoh 4-8 jam Tahap 3 → Perhatikan trend jangka sederhana dalam tempoh 1-2 hari (strategi yang biasa digunakan) Aras 4 → Perhatikan julat harga 2-4 hari Tahap 5 → Perhatikan trend utama sepanjang 4-8 hari

Perbandingan keputusan sebenar:

Harga BTC asal (carta 1 jam):99500, 99800, 99200, 100200, 99800, 100500, 100100, ...

Pemprosesan Tahap 1: 99600, 99650, 99500, 99900, 99950, 100200, 100250, … (Sedikit lebih lancar, tetapi turun naik masih kelihatan)

Pemprosesan Tahap 3: 99620, 99650, 99700, 99800, 99950, 100100, 100200, … (Diratakan, menunjukkan trend jangka sederhana)

Pemprosesan Tahap 5: 99630, 99640, 99660, 99700, 99760, 99840, 99930, … (Sangat lancar, hanya menunjukkan arah umum)

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet? Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet? Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet? Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet? Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?

Prinsip pemilihannya mudah: gunakan Tahap yang sepadan berdasarkan tempoh pegangan anda.

Scalping 15 minit → Tahap 1-2
Dagangan intraday → Tahap 2-3
Lakukan ayunan selama beberapa hari → Tahap 3-4
Analisis trend jangka panjang → Tahap 4-5


VII. Idea Aplikasi Praktikal

Aplikasi transformasi wavelet dalam perdagangan adalah sangat langsung: gunakan lengkung harga terlicin yang dijana untuk menentukan arah trend, dan berdagang apabila trend berubah. Secara khususnya, jika harga penutupan terlicin lebih tinggi daripada sebelumnya, ia menunjukkan trend menaik, jadi terus beli; jika harga penutupan terlicin lebih rendah daripada sebelumnya, ia menunjukkan trend menurun, jadi tutup posisi atau terus jual. Logik ini berkesan kerana wavelet telah menapis turun naik rawak jangka pendek, meninggalkan “naik” atau “turun” sebagai kebarangkalian tinggi perubahan trend tulen, bukannya isyarat palsu yang disebabkan oleh hingar.

# 执行小波变换
transformed = transformer.transform_ohlc(df)

# 获取最近两根K线的平滑收盘价
w_close_current = transformed['w_close'].values[-1]  # 当前平滑收盘价
w_close_prev = transformed['w_close'].values[-2]     # 前一根平滑收盘价

# 判断趋势方向
signal = 0
if w_close_current > w_close_prev:
    signal = 1   # 平滑价格向上 → 做多
elif w_close_current < w_close_prev:
    signal = -1  # 平滑价格向下 → 做空

# 获取账户信息
account = exchange.GetAccount()
ticker = exchange.GetTicker()

if not account or not ticker:
    Log("[Warning] Failed to get account/ticker info")
    Sleep(5000)
    continue

current_price = ticker['Last']

Log(f"[Price] 原始: {df['Close'].values[-1]:.2f}, "
    f"平滑当前: {w_close_current:.2f}, 平滑前值: {w_close_prev:.2f}")
Log(f"[Trend] {'↑ 向上' if signal == 1 else '↓ 向下' if signal == -1 else '→ 横盘'}")

# 执行交易逻辑
if signal == 1 and position != 1:
    # 平滑价格向上 → 做多
    Log(f"[信号] 趋势向上,开多 @ {current_price:.2f}")
    
    if position == -1:
        # 先平空仓
        exchange.SetDirection("closesell")
        exchange.Buy(current_price, 1)
        Log(f"[平仓] 平空仓")
    
    # 开多仓
    exchange.SetDirection("buy")
    exchange.Buy(current_price, 1)
    Log(f"[开仓] 开多仓")
    position = 1
    
elif signal == -1 and position != -1:
    # 平滑价格向下 → 做空
    Log(f"[信号] 趋势向下,开空 @ {current_price:.2f}")
    
    if position == 1:
        # 先平多仓
        exchange.SetDirection("closebuy")
        exchange.Sell(current_price, 1)
        Log(f"[平仓] 平多仓")
    
    # 开空仓
    exchange.SetDirection("sell")
    exchange.Sell(current_price, 1)
    Log(f"[开仓] 开空仓")
    position = -1

else:
    Log(f"[持仓] 当前{'多头' if position == 1 else '空头' if position == -1 else '空仓'},无需操作")

Membongkar Tiga Teknik Penting Pemprosesan Data Kewangan: Apakah Sebenarnya Transformasi Wavelet?

Sudah tentu, dalam praktiknya, ia tidak semudah itu. Anda boleh menggunakan berbilang tahap wavelet secara serentak, seperti Tahap 2 yang menunjukkan trend jangka pendek dan Tahap 4 yang menunjukkan trend jangka panjang. Hanya buka posisi apabila kedua-duanya bergerak dalam arah yang sama, yang mengurangkan isyarat palsu dengan ketara. Anda juga boleh menambah syarat penapisan lain, seperti memerlukan peningkatan volum dagangan, turun naik yang cukup tinggi, atau penembusan harga di atas tahap utama; semuanya ini boleh meningkatkan kadar kemenangan. Untuk pesanan henti rugi, anda boleh menetapkannya secara dinamik menggunakan julat turun naik harga yang diratakan wavelet; contohnya, henti rugi jika harga jatuh di bawah harga yang diratakan tolak 2 kali ganda ATR. Dalam pengurusan posisi, semakin jelas trend (semakin curam cerun harga yang diratakan), semakin berat saiz posisi; jika trend tidak jelas, gunakan posisi yang lebih ringan atau kekal di luar.

Tetapi idea terasnya tetap sama: gunakan wavelet untuk mengubah harga yang bising menjadi trend yang jelas, dan kemudian buat penilaian berdasarkan trend yang jelas tersebut. Ini jauh lebih dipercayai daripada melihat secara langsung kenaikan dan penurunan pada carta candlestick asal, kerana carta candlestick asal mungkin naik 3% hari ini, turun 2% esok, dan naik 4% lusa. Anda tidak dapat membezakan sama ada ia adalah trend atau turun naik. Lengkung yang diproses oleh wavelet akan memberitahu anda “trend keseluruhan dalam tempoh ini adalah menaik, walaupun terdapat turun naik di antara”.


VIII. Kesimpulan: Pandangan Rasional tentang “Pendekatan Tiga Serampang”

Dari segi kesan pelicinan praktikal, transformasi wavelet sememangnya boleh memainkan peranan dalam pemprosesan data kewangan: ia boleh menapis beberapa hingar jangka pendek dan membantu mengekstrak maklumat trend yang agak jelas. Walau bagaimanapun, teknik ini juga mempunyai batasan yang ketara—Masalah kelewatan tidak dapat dielakkan sepenuhnya.Walau bagaimanapun, ia hanya boleh memproses data sejarah dan tidak dapat meramalkan trend masa hadapan. Tambahan pula, kesan penggunaan transformasi wavelet sahaja agak terhad; ia perlu digabungkan dengan kaedah analisis lain dan langkah kawalan risiko untuk membina sistem perdagangan yang lengkap.

Sebab utama bagi batasan ini terletak pada sifat unik pasaran kewangan. Dalam bidang pemprosesan isyarat tradisional seperti pengecaman pertuturan dan pemprosesan imej, ciri-ciri hingar adalah agak stabil, dan corak isyarat cenderung berulang. Oleh itu, transformasi gelombang kecil boleh memisahkan isyarat daripada hingar dengan berkesan. Walau bagaimanapun, pasaran kewangan adalah sama sekali berbeza: turun naik yang dianggap sebagai “hingar” hari ini mungkin menjadi “isyarat” yang mencerminkan perubahan pasaran esok; model analitikal yang berkesan sekarang mungkin menjadi tidak berkesan pada masa hadapan.Pasaran itu sendiri tidak pegun dan sentiasa berubah secara dinamik.Tiada hukum yang tidak berubah dalam transformasi wavelet, yang menghendaki aplikasi transformasi wavelet dalam bidang kewangan mesti diselaraskan secara fleksibel mengikut persekitaran pasaran tertentu.

Apabila anda melihat seseorang membesar-besarkan kesan sebenar transformasi wavelet dan transformasi Fourier, cuba tanya soalan-soalan ini: Jenis wavelet yang manakah digunakan? Apakah asas untuk memilih jenis ini dan bukannya yang lain? Bagaimanakah tahap pelicinan ditetapkan? Adakah terdapat keputusan ujian balik dan prosedur pemilihan parameter yang sepadan?Mereka yang benar-benar mempunyai pengetahuan profesional akan dapat menerangkan butiran teknikal utama ini dengan jelas.

Berdasarkan pengetahuan kami yang terhad, kami menjalankan penerokaan praktikal ini.Idea terasnya adalah untuk berkongsi konsep aplikasi transformasi wavelet dengan cara yang mudah dan senang difahami.Artikel ini bertujuan untuk membantu pembaca memperoleh pemahaman asas tentang teknologi ini. Kami sangat menghargai penyelidik kuantitatif yang terlibat secara mendalam dalam bidang ini; jika anda pakar dalam bidang ini, anda dialu-alukan untuk menunjukkan sebarang kekurangan dalam artikel ini—seperti asas teori untuk pemilihan parameter wavelet, kaedah pengoptimuman untuk kombinasi berbilang skala dan laluan pelaksanaan untuk pemilihan wavelet adaptif. Kami dengan rendah hati akan menerima cadangan anda dan terus menambah baik kandungannya.

Fungsi pemplotan: Digunakan dalam enjin ujian belakang tempatan pencipta

'''backtest
start: 2025-12-17 00:00:00
end: 2025-12-23 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","fee":[0,0]}]
'''
from fmz import *
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

task = VCtx(__doc__)

# ==================== 小波系数库 ====================
class WaveletCoefficients:
    """Wavelet Coefficients Definition"""
    
    @staticmethod
    def get_coeffs(wavelet_name):
        """Get coefficients for different wavelet types"""
        coeffs = {
            "Haar": [0.5, 0.5],
            
            "Daubechies 4": [
                0.48296291314453414,
                0.8365163037378079,
                0.22414386804201339,
                -0.12940952255126037
            ],
            
            "Symlet 4": [
                -0.05357, -0.02096, 0.35238,
                0.56833, 0.21062, -0.07007,
                -0.01941, 0.03268
            ],
            
            "Biorthogonal 3.3": [
                -0.06629, 0.28289, 0.63678,
                0.28289, -0.06629
            ],
            
            "Mexican Hat (Ricker)": [
                -0.1, 0.0, 0.4, 0.8, 0.4, 0.0, -0.1
            ],
            
            "Morlet (Gaussian)": [
                0.0625, 0.25, 0.375, 0.25, 0.0625
            ],
            
            "Discrete Meyer (Dmey)": [
                -0.015, -0.025, 0.0,
                0.28, 0.52, 0.28,
                0.0, -0.025, -0.015
            ]
        }
        
        return coeffs.get(wavelet_name, coeffs["Mexican Hat (Ricker)"])


# ==================== 小波变换引擎 ====================
class WaveletTransform:
    """Wavelet Transform Engine"""
    
    def __init__(self, wavelet_type="Mexican Hat (Ricker)", smoothing_level=3):
        self.wavelet_type = wavelet_type
        self.smoothing_level = smoothing_level
        self.coeffs = WaveletCoefficients.get_coeffs(wavelet_type)
    
    def convolve(self, src, coeffs, step):
        """
        Convolution operation - Core algorithm
        
        Args:
            src: Source data sequence
            coeffs: Wavelet coefficients
            step: Sampling step
        
        Returns:
            Convolved value
        """
        sum_val = 0.0
        sum_w = 0.0
        
        for i, weight in enumerate(coeffs):
            idx = i * step
            if idx < len(src):
                val = src[idx]
                sum_val += val * weight
                sum_w += weight
        
        # Normalization - Critical fix
        return sum_val / sum_w if sum_w != 0 else sum_val
    
    def calc_level(self, data, target_level):
        """
        Calculate wavelet transform for specified level
        
        Args:
            data: Original data array
            target_level: Target smoothing level
        
        Returns:
            Transformed data array
        """
        result = []
        coeffs = self.coeffs
        
        for i in range(len(data)):
            # Get data from current position backwards
            src = data[max(0, i - 50):i + 1][::-1]
            
            # Level 1
            val = self.convolve(src, coeffs, 1)
            
            # Level 2
            if target_level >= 2:
                src_temp = [val] + [self.convolve(data[max(0, j - 50):j + 1][::-1], coeffs, 1) 
                                   for j in range(max(0, i - 10), i)][::-1]
                val = self.convolve(src_temp, coeffs, 2)
            
            # Level 3
            if target_level >= 3:
                val = self.convolve([val] * len(coeffs), coeffs, 4)
            
            # Level 4+
            if target_level >= 4:
                val = self.convolve([val] * len(coeffs), coeffs, 8)
            
            result.append(val)
        
        return np.array(result)
    
    def transform_ohlc(self, df):
        """
        Perform wavelet transform on OHLC data
        
        Args:
            df: DataFrame with Open/High/Low/Close
        
        Returns:
            Transformed DataFrame
        """
        result_df = df.copy()
        
        # Transform each price series
        result_df['w_open'] = self.calc_level(df['Open'].values, self.smoothing_level)
        result_df['w_high'] = self.calc_level(df['High'].values, self.smoothing_level)
        result_df['w_low'] = self.calc_level(df['Low'].values, self.smoothing_level)
        result_df['w_close'] = self.calc_level(df['Close'].values, self.smoothing_level)
        
        # Reconstruct logically consistent candlesticks
        result_df['real_high'] = result_df[['w_high', 'w_low', 'w_open', 'w_close']].max(axis=1)
        result_df['real_low'] = result_df[['w_high', 'w_low', 'w_open', 'w_close']].min(axis=1)
        
        return result_df


# ==================== K线图可视化工具 ====================
class WaveletCandlestickVisualizer:
    """Wavelet Candlestick Visualization"""
    
    @staticmethod
    def plot_single_wavelet(df, wavelet_type, smoothing_level=3, n_bars=200):
        """
        Plot single wavelet type comparison
        
        Args:
            df: Original candlestick data
            wavelet_type: Wavelet type
            smoothing_level: Smoothing level
            n_bars: Number of bars to display
        """
        # Take only last n_bars
        df_plot = df.iloc[-n_bars:].copy()
        
        # Create figure
        fig, ax = plt.subplots(figsize=(20, 8))
        
        # Perform wavelet transform
        transformer = WaveletTransform(wavelet_type, smoothing_level)
        transformed = transformer.transform_ohlc(df)
        transformed_plot = transformed.iloc[-n_bars:].copy()
        
        # Draw original candlesticks (gray background)
        WaveletCandlestickVisualizer._draw_candlesticks(
            ax, df_plot, 
            color_up='lightgray', 
            color_down='lightgray',
            alpha=0.3,
            label='Original Candles'
        )
        
        # Draw wavelet smoothed candlesticks
        WaveletCandlestickVisualizer._draw_candlesticks(
            ax, transformed_plot,
            use_wavelet=True,
            color_up='#26A69A',  # Green
            color_down='#EF5350',  # Red
            alpha=0.9,
            linewidth=1.2,
            label=f'{wavelet_type} Smoothed (Level {smoothing_level})'
        )
        
        # Set title and labels
        ax.set_title(f'{wavelet_type} Wavelet (Level {smoothing_level}) - Candlestick Comparison', 
                    fontsize=16, fontweight='bold', pad=20)
        ax.set_ylabel('Price (USDT)', fontsize=13)
        ax.set_xlabel('Time', fontsize=13)
        ax.grid(True, alpha=0.2, linestyle='--')
        ax.legend(loc='upper left', fontsize=12)
        
        # Format x-axis
        ax.set_xlim(-1, len(df_plot))
        ax.set_xticks(range(0, len(df_plot), max(1, len(df_plot) // 10)))
        ax.set_xticklabels([df_plot.index[i].strftime('%m-%d %H:%M') 
                           for i in range(0, len(df_plot), max(1, len(df_plot) // 10))], 
                          rotation=45, ha='right')
        
        plt.tight_layout()
        plt.show()
        return fig
    
    @staticmethod
    def plot_single_level(df, wavelet_type, level, n_bars=200):
        """
        Plot single smoothing level
        
        Args:
            df: Original candlestick data
            wavelet_type: Wavelet type
            level: Smoothing level
            n_bars: Number of bars to display
        """
        # Take only last n_bars
        df_plot = df.iloc[-n_bars:].copy()
        
        # Create figure
        fig, ax = plt.subplots(figsize=(20, 8))
        
        # Perform wavelet transform
        transformer = WaveletTransform(wavelet_type, level)
        transformed = transformer.transform_ohlc(df)
        transformed_plot = transformed.iloc[-n_bars:].copy()
        
        # Draw original candlesticks
        WaveletCandlestickVisualizer._draw_candlesticks(
            ax, df_plot,
            color_up='lightgray',
            color_down='lightgray',
            alpha=0.3,
            label='Original Candles'
        )
        
        # Draw wavelet smoothed candlesticks
        WaveletCandlestickVisualizer._draw_candlesticks(
            ax, transformed_plot,
            use_wavelet=True,
            color_up='#26A69A',
            color_down='#EF5350',
            alpha=0.9,
            linewidth=1.2,
            label=f'Level {level} Smoothed'
        )
        
        # Set title and labels
        ax.set_title(f'{wavelet_type} - Smoothing Level {level} Effect', 
                    fontsize=16, fontweight='bold', pad=20)
        ax.set_ylabel('Price (USDT)', fontsize=13)
        ax.set_xlabel('Time', fontsize=13)
        ax.grid(True, alpha=0.2, linestyle='--')
        ax.legend(loc='upper left', fontsize=12)
        
        # Format x-axis
        ax.set_xlim(-1, len(df_plot))
        ax.set_xticks(range(0, len(df_plot), max(1, len(df_plot) // 10)))
        ax.set_xticklabels([df_plot.index[i].strftime('%m-%d %H:%M') 
                           for i in range(0, len(df_plot), max(1, len(df_plot) // 10))], 
                          rotation=45, ha='right')
        
        plt.tight_layout()
        plt.show()
        return fig
    
    @staticmethod
    def _draw_candlesticks(ax, df, use_wavelet=False, color_up='green', 
                          color_down='red', alpha=1.0, linewidth=1.0, label=''):
        """
        Draw candlestick chart
        
        Args:
            ax: Matplotlib axis
            df: Data DataFrame
            use_wavelet: Whether to use wavelet data
            color_up: Up color
            color_down: Down color
            alpha: Transparency
            linewidth: Line width
            label: Legend label
        """
        if use_wavelet:
            opens = df['w_open'].values
            highs = df['real_high'].values
            lows = df['real_low'].values
            closes = df['w_close'].values
        else:
            opens = df['Open'].values
            highs = df['High'].values
            lows = df['Low'].values
            closes = df['Close'].values
        
        for i in range(len(df)):
            x = i
            open_price = opens[i]
            high_price = highs[i]
            low_price = lows[i]
            close_price = closes[i]
            
            color = color_up if close_price >= open_price else color_down
            
            # Draw wick
            ax.plot([x, x], [low_price, high_price], 
                   color=color, linewidth=linewidth, alpha=alpha)
            
            # Draw body
            height = abs(close_price - open_price)
            bottom = min(open_price, close_price)
            
            rect = Rectangle((x - 0.3, bottom), 0.6, height,
                           facecolor=color, edgecolor=color,
                           alpha=alpha, linewidth=linewidth)
            ax.add_patch(rect)
        
        # Add legend (only once)
        if label:
            ax.plot([], [], color=color_up, linewidth=3, alpha=alpha, label=label)


# ==================== 主函数 ====================
def main():
    """Main execution flow"""
    exchange.SetCurrency("BTC_USDT")
    exchange.SetContractType("swap")
    
    # Get candlestick data
    records = exchange.GetRecords(PERIOD_H1, 500)
    
    # Convert to DataFrame
    df = pd.DataFrame(records, columns=['Time', 'Open', 'High', 'Low', 'Close', 'Volume'])
    df['Time'] = pd.to_datetime(df['Time'], unit='ms')
    df.set_index('Time', inplace=True)
    
    print(f"Data loaded: {len(df)} bars")
    print(f"Time range: {df.index[0]} to {df.index[-1]}")
    print(f"Price range: ${df['Low'].min():.2f} - ${df['High'].max():.2f}")
    
    return df


# ==================== 执行绘图 ====================
try:
    # Get candlestick data
    kline = main()
    
    print("\n" + "="*70)
    print("Generating Wavelet Candlestick Charts (Each in Separate Window)...")
    print("="*70)
    
    # ========== Chart Series 1: Different Wavelet Types ==========
    print("\n[Series 1] Comparing Different Wavelet Types")
    print("-" * 70)
    
    wavelet_types = [
        "Haar",
        "Daubechies 4",
        "Symlet 4",
        "Biorthogonal 3.3",
        "Mexican Hat (Ricker)",
        "Morlet (Gaussian)",
        "Discrete Meyer (Dmey)"  # ✅ 添加了 Discrete Meyer
    ]
    
    for i, wavelet_type in enumerate(wavelet_types, 1):
        print(f"  Chart {i}/{len(wavelet_types)}: {wavelet_type}")
        fig = WaveletCandlestickVisualizer.plot_single_wavelet(
            kline, 
            wavelet_type=wavelet_type,
            smoothing_level=3, 
            n_bars=150
        )
    
    # ========== Chart Series 2: Different Smoothing Levels ==========
    print("\n[Series 2] Comparing Different Smoothing Levels")
    print("-" * 70)
    
    levels = [1, 2, 3, 4, 5]
    
    for i, level in enumerate(levels, 1):
        print(f"  Chart {i}/5: Level {level}")
        fig = WaveletCandlestickVisualizer.plot_single_level(
            kline, 
            wavelet_type="Mexican Hat (Ricker)",
            level=level,
            n_bars=150
        )
    
    print("\n" + "="*70)
    print("All charts generated successfully!")
    print(f"Total charts: {len(wavelet_types) + len(levels)} ({len(wavelet_types)} wavelets + {len(levels)} levels)")
    print("="*70)
    
except Exception as e:
    print(f"Error: {str(e)}")
    import traceback
    print(traceback.format_exc())
finally:
    print("\nStrategy testing completed.")

Fungsi transaksi: Digunakan pada platform Pencipta

'''backtest
start: 2025-01-17 00:00:00
end: 2025-12-23 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","fee":[0,0]}]
'''

import numpy as np
import pandas as pd

# ==================== 小波系数库 ====================
class WaveletCoefficients:
    """与上部分函数一致"""

# ==================== 小波变换引擎 ====================
class WaveletTransform:
    """与上部分函数一致"""
 
def main():
    """小波交易主函数 - 基于平滑价格趋势"""
    
    # ========== 配置参数 ==========
    WAVELET_TYPE = "Mexican Hat (Ricker)"  # 小波类型
    SMOOTHING_LEVEL = 1                     # 平滑阶数
    
    # 初始化
    exchange.SetCurrency("BTC_USDT")
    exchange.SetContractType("swap")
    
    Log(f"=" * 70)
    Log(f"Wavelet Trend Following Strategy")
    Log(f"Wavelet: {WAVELET_TYPE}, Level: {SMOOTHING_LEVEL}")
    Log(f"Logic: 平滑收盘价向上→做多, 平滑收盘价向下→做空")
    Log(f"=" * 70)
    
    # 初始化小波变换器
    transformer = WaveletTransform(WAVELET_TYPE, SMOOTHING_LEVEL)
    
    # 持仓状态
    position = 0  # 0: 无持仓, 1: 多头, -1: 空头
    
    while True:

        # 获取K线数据
        records = exchange.GetRecords(PERIOD_H1, 500)
        if not records:
            Log("[Warning] Failed to get kline data")
            Sleep(5000)
            continue
        
        df = pd.DataFrame(records, columns=['Time', 'Open', 'High', 'Low', 'Close', 'Volume'])
        df['Time'] = pd.to_datetime(df['Time'], unit='ms')
        df.set_index('Time', inplace=True)
        
        # 执行小波变换
        transformed = transformer.transform_ohlc(df)
        
        # 获取最近两根K线的平滑收盘价
        w_close_current = transformed['w_close'].values[-1]  # 当前平滑收盘价
        w_close_prev = transformed['w_close'].values[-2]     # 前一根平滑收盘价
        
        # 判断趋势方向
        signal = 0
        if w_close_current > w_close_prev:
            signal = 1   # 平滑价格向上 → 做多
        elif w_close_current < w_close_prev:
            signal = -1  # 平滑价格向下 → 做空
        
        # 获取账户信息
        account = exchange.GetAccount()
        ticker = exchange.GetTicker()
        
        if not account or not ticker:
            Log("[Warning] Failed to get account/ticker info")
            Sleep(5000)
            continue
        
        current_price = ticker['Last']
        
        Log(f"[Price] 原始: {df['Close'].values[-1]:.2f}, "
            f"平滑当前: {w_close_current:.2f}, 平滑前值: {w_close_prev:.2f}")
        Log(f"[Trend] {'↑ 向上' if signal == 1 else '↓ 向下' if signal == -1 else '→ 横盘'}")
        
        # 执行交易逻辑
        if signal == 1 and position != 1:
            # 平滑价格向上 → 做多
            Log(f"[信号] 趋势向上,开多 @ {current_price:.2f}")
            
            if position == -1:
                # 先平空仓
                exchange.SetDirection("closesell")
                exchange.Buy(current_price, 1)
                Log(f"[平仓] 平空仓")
            
            # 开多仓
            exchange.SetDirection("buy")
            exchange.Buy(current_price, 1)
            Log(f"[开仓] 开多仓")
            position = 1
            
        elif signal == -1 and position != -1:
            # 平滑价格向下 → 做空
            Log(f"[信号] 趋势向下,开空 @ {current_price:.2f}")
            
            if position == 1:
                # 先平多仓
                exchange.SetDirection("closebuy")
                exchange.Sell(current_price, 1)
                Log(f"[平仓] 平多仓")
            
            # 开空仓
            exchange.SetDirection("sell")
            exchange.Sell(current_price, 1)
            Log(f"[开仓] 开空仓")
            position = -1
        
        else:
            Log(f"[持仓] 当前{'多头' if position == 1 else '空头' if position == -1 else '空仓'},无需操作")
        
        Log(f"[账户] 余额: {account['Balance']:.2f}, 权益: {account['Equity']:.2f}")
        Log("-" * 70)
        
        Sleep(60000 * 60)