[TOC]

Artikel ini adalahSebuah Tinjauan Ilmiah Populer tentang Transformasi Wavelet untuk Praktik PerdaganganKode ini adalah versi pengajaran yang disederhanakan (menghilangkan langkah-langkah kompleks seperti dekomposisi multi-level, peredaman derau ambang batas, dan rekonstruksi transformasi invers dari wavelet standar), hanya mempertahankan ide-ide intinya:Gunakan koefisien wavelet untuk melakukan penghalusan multi-skala pada harga guna mengekstrak informasi tren.Cocok untuk pengembangan strategi dan validasi cepat, tetapi tidak untuk penelitian akademis atau publikasi makalah.
Mereka yang sering menjelajahi topik keuangan dan kuantitatif di Zhihu pasti pernah melihat skenario ini:
Beberapa “pakar” terus mengatakan:
Dia membuat semua orang tercengang, seolah-olah dia telah menguasai senjata nuklir berupa perdagangan kuantitatif.
Tapi kamu ingin dia menunjukkan kodenya padamu?
“Ini… adalah rahasia dagang, dan saya tidak dapat mengungkapkannya.”
Mintalah dia untuk menjelaskan prinsipnya.
“Ini… melibatkan matematika tingkat lanjut, kamu tidak akan mengerti meskipun aku menjelaskannya kepadamu.”
Hari ini, kita akan menjelajahi topik-topik yang sering disebutkan oleh para “pakar Zhihu” ini, memperkenalkan aplikasi praktis transformasi wavelet di pasar keuangan, dan membantu semua orang mengembangkan pemahaman yang benar tentang teknologi ini.
Bayangkan Anda sedang mendengarkan sebuah lagu, tetapi ada suara bising di latar belakang rekaman tersebut:
Rekaman asli = suara manusia + kebisingan latar belakang + statis
Transformasi wavelet itu sepertiFilter Pintar:
Beralihlah ke pasar keuangan:
Harga Asli = Tren Sebenarnya + Fluktuasi Jangka Pendek + Gangguan Acak
Transformasi wavelet dapat membantu Anda:
Inti sari dari transformasi wavelet adalahUraikan sinyal asli menggunakan serangkaian “fungsi basis” (wavelet) tertentu.。
Bayangkan Anda ingin mendeskripsikan penampilan seseorang:
Dalam harga finansial:
Seri harga asli = Fungsi basis 1 × Bobot 1 + Fungsi basis 2 × Bobot 2 + … + Derau
Fungsi basis adalah “template” yang sesuai dengan koefisien wavelet.Berbagai jenis wavelet (Haar, Daubechies, Mexican Hat, dll.) menggunakan templat yang berbeda, sama seperti menggunakan “ekstraktor fitur” yang berbeda untuk menguraikan harga.
Transformasi wavelet pada dasarnya adalah…Bank filter multiskala:
Filter frekuensi tinggi → Mampu menangkap fluktuasi cepat (noise harian, fluktuasi tingkat tick) Filter frekuensi menengah → Menangkap tren jangka menengah (rentang waktu dari beberapa jam hingga beberapa hari). Filter frekuensi rendah → Menangkap tren jangka panjang (tren mingguan dan bulanan).
Mengapa disebut “wavelet”?
Masalah dengan menggunakan gelombang sinus untuk menganalisis harga keuangan: Gelombang sinus mengasumsikan bahwa sinyal tersebut berulang secara periodik, tetapi pasar keuangan tidak! BTC mungkin naik 10% hari ini dan turun 8% besok, tanpa siklus sama sekali.
Keunggulan wavelet:Analisis lokalisasiIni dapat memberi tahu Anda “tren harga sebagian besar naik antara pukul 3 sore dan 5 sore pada tanggal 20 Desember 2025”, daripada kesimpulan umum seperti “pasar secara keseluruhan berfluktuasi”.
Transformasi wavelet adalahDapat dibalikIni sangat penting!
Harga asli —> Dekomposisi wavelet —> Komponen tren + Komponen volatilitas + Komponen noise Komponen tren + komponen volatilitas + komponen noise —> rekonstruksi wavelet —> harga asli
Proses refactoringTujuannya adalah untuk menguraikan komponen-komponen individual.Gabungkan kembali secara selektif:
Hanya gunakan komponen tren selama rekonstruksi.
Setelah dekomposisi, diperoleh hasil sebagai berikut.
Dalam transaksi sebenarnya, kita biasanyaRekonstruksi hanya bagian frekuensi rendah.(Tren) Komponen frekuensi tinggi (noise) langsung dibuang. Inilah prinsip “pengurangan noise” wavelet.
Mari kita lewati rumus integral yang rumit dan jelaskan dengan bahasa yang mudah dipahami:
Transformasi wavelet = rata-rata tertimbang dari rangkaian harga menggunakan serangkaian “koefisien wavelet”
Rumus dasar:
Meratakan harga[i] = Σ(harga asli)[i-j] × koefisien wavelet[j]) / Σ(koefisien wavelet)[j])
Perspektif filter:
Harga asli disaring melalui filter wavelet → komponen dengan frekuensi berbeda “dipilih”.
Kuncinya adalahPemilihan koefisien wavelet:
Misalnya:
Dengan asumsi Anda menggunakan wavelet Daubechies 4, koefisiennya adalah[0.483, 0.837, 0.224, -0.129]:
Kumpulan koefisien ini mendefinisikan sebuah filter:
Transformasi wavelet selesai ketika Anda “menggeser” filter ini di seluruh rangkaian harga. Setiap pergeseran melibatkan perhitungan.Rata-rata tertimbang harga dalam periode waktu saat iniBobot tersebut adalah koefisien wavelet.
Mengapa ia dapat “menguraikan” sinyal?
Karena dapat dibuktikan secara matematis bahwa:Sinyal apa pun dapat direpresentasikan sebagai kombinasi linier dari fungsi basis wavelet.Sama seperti warna apa pun dapat dibuat dengan mencampur tiga warna primer RGB, rangkaian harga apa pun dapat diperoleh dengan menggabungkan fungsi basis wavelet. Berbagai jenis wavelet menyediakan “perpustakaan fungsi basis” yang berbeda, yang cocok untuk berbagai jenis analisis sinyal.
Dalam buku teks pemrosesan sinyal, transformasi wavelet biasanya melibatkan hal-hal yang kompleks…Dekomposisi multi-level, rekonstruksi, dan pengurangan derau ambang batasTangga:
Alur kerja analisis wavelet lengkap:
TetapiPenerapan praktis transaksi keuanganDi Tiongkok, kita tidak perlu membuatnya serumit itu. Karena:
1. Trading hanya membutuhkan arah tren; rekonstruksi sempurna tidak diperlukan.
Penelitian akademis mungkin memerlukan kesalahan rekonstruksi kurang dari 0,01%, tetapi dalam perdagangan, hal itu sudah cukup untuk menentukan apakah harga akan naik atau turun. Bahkan jika rekonstruksi memiliki kesalahan 5%, strategi tersebut masih dapat menguntungkan selama arah trennya benar.
2. Persyaratan waktu nyata menyederhanakan perhitungan.
Dekomposisi wavelet lengkap memerlukan perhitungan rekursif dari beberapa lapisan koefisien, yang dapat menyebabkan latensi dalam perdagangan frekuensi tinggi. Konvolusi langsung, di sisi lain, dapat diselesaikan dalam hitungan milidetik, memenuhi kebutuhan perdagangan langsung.
3. Karakteristik Khusus Sinyal Keuangan
Harga keuangan bukanlah sinyal yang stabil dan tidak menunjukkan siklus yang ketat. Dekomposisi frekuensi yang kompleks tidak terlalu berarti di sini; ekstraksi tren sederhana lebih praktis.
Oleh karena itu, artikel iniMengekstraksi esensi dari transformasi wavelet.Berfokus pada aspek-aspek paling praktis dari pasar keuangan:
Penyederhanaan Inti 1: Gunakan hanya koefisien perkiraan (tren frekuensi rendah)
Dekomposisi wavelet tradisional → koefisien aproksimasi + koefisien detail (multi-layer) Aplikasi ini: Hanya mempertahankan koefisien perkiraan → langsung mendapatkan tren yang dihaluskan.
Penyederhanaan Inti 2: Konvolusi Langsung, tanpa Pengurangan Derau Ambang Batas
Dekomposisi wavelet tradisional → penentuan ambang batas koefisien detail → rekonstruksi Aplikasi ini: Konvolusi langsung → untuk mendapatkan harga yang dihaluskan
Penyederhanaan Inti 3: Abaikan Pemrosesan Batas
Wavelet tradisional memerlukan pemrosesan seperti perluasan simetris dan perluasan periodik dari batas sinyal. Aplikasi ini hanya berfokus pada bagian tengah; kesalahan pada bagian batas dapat diterima.
Metode implementasi: Konvolusi filter
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…Inti dari filter wavelet:
stepParameter memungkinkan penghalusan multi-level (Level 1/2/3…).Mengapa penyederhanaan ini masuk akal?
Karena persyaratan penting dari transaksi adalah:Menemukan Tren dalam KebisinganKoefisien aproksimasi transformasi wavelet itu sendiri merupakan “filter lolos rendah” untuk sinyal, yang mempertahankan komponen tren frekuensi rendah, yang正是 apa yang kita butuhkan.
Meskipun analisis wavelet lengkap lebih akurat, dalam perdagangan keuangan:
menggunakanMesin pengujian balik lokal dari platform Inventor Quantization (FMZ)Mendapatkan data sangat mudah!
'''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()
Tidak diperlukan integrasi API yang kompleks atau pembersihan data; data candlestick standar dapat diperoleh secara langsung. Hal ini memungkinkan kita untuk dengan cepat memverifikasi efek sebenarnya dari tujuh jenis wavelet, daripada terjebak dalam pemrosesan data.
Dengan membandingkan kinerja tujuh jenis wavelet umum (Haar, Daubechies 4, Symlet 4, Biorthogonal 3.3, Mexican Hat, Morlet, dan Discrete Meyer) pada harga mata uang kripto, demonstrasi visual berikut disajikan:
Fokusnya bukanlah pada ketelitian penurunan matematis, tetapi pada perbandingan visual dari hasil praktis.Hal ini membantu para trader mengembangkan pemahaman intuitif dan memilih jenis wavelet yang sesuai dengan strategi mereka.
Wavelet Haar adalah jenis wavelet paling dasar, hanya memiliki dua koefisien:[0.5, 0.5]Pada dasarnya, ini adalah rata-rata sederhana dari dua harga yang berdekatan.
Kode inti:
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 awalnya berfluktuasi liar (dari 99.000 hingga 102.000) menjadi relatif stabil setelah pemrosesan Haar. Ini adalah efek dari “penghilangan noise” wavelet - menghaluskan fluktuasi jangka pendek yang hebat, memungkinkan Anda untuk melihat tren harga yang lebih halus.

Daubechies 4 (disingkat db4) adalah salah satu wavelet yang paling umum digunakan dalam bidang teknik. Koefisiennya adalah:[0.483, 0.837, 0.224, -0.129]Perhatikan bahwa koefisien terakhir adalah…angka negatifItulah yang membuatnya unik.
Kode inti:
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
Fitur Utama:Bobot candlestick sebelumnya (0,837) lebih besar daripada bobot harga saat ini (0,483)! Ini berarti bahwa db4 lebih menekankan pada “harga yang baru saja terjadi”, dan koefisien bobot negatif akan memiliki efek “penyeimbang” pada harga sebelumnya, sehingga semakin meningkatkan kelancaran pergerakan harga.

Symlet 4 adalah versi perbaikan dari Daubechies, yang bertujuan untuk simetri yang lebih baik. Koefisien:[-0.076, -0.030, 0.498, 0.804, 0.298, -0.099, -0.013, 0.032]。
Kode inti:
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都强,但反应速度更慢
Fitur Utama:Jendela dengan panjang 8 candlestick memungkinkan “memori” harga yang lebih panjang. Pembalikan tren yang sebenarnya mungkin tidak terlihat pada kurva yang mulus hingga setelah 8 candlestick berlalu.

Biorthogonal 3.3 (disingkat sebagai bior3.3) adalah wavelet yang simetris sempurna dengan koefisien:[-0.066, 0.283, 0.637, 0.283, -0.066]。
Kode inti:
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
Fitur Utama:Simetri memastikan tidak adanya “distorsi fase” - kurva yang dihaluskan tidak akan bergeser ke kiri atau ke kanan tanpa alasan yang jelas.

Koefisien Mexican Hat (juga disebut wavelet Ricker):[-0.1, 0.0, 0.4, 0.8, 0.4, 0.0, -0.1]Bentuknya seperti topi sombrero Meksiko.
Kode inti:
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
Fitur Utama:Struktur “besar di tengah, negatif di kedua ujungnya” membuatnya sangat baik dalam pendeteksian.titik infleksi- Momen kritis ketika harga berbalik dari tren naik menjadi tren turun (atau sebaliknya). Koefisien pembobotan negatif “menghukum” harga yang jauh, dengan cepat menangkap perubahan tren.

Wavelet Morlet didasarkan pada distribusi Gaussian (normal), dengan koefisien:[0.0625, 0.25, 0.375, 0.25, 0.0625]。
Kode inti:
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
Fitur Utama:Wavelet ini adalah yang paling “lembut” di antara semua wavelet, tidak memiliki bobot negatif, dan semua harga dimasukkan secara perlahan ke dalam perhitungan. Kurva yang dihasilkan sangat halus, tetapi kekurangannya adalah respons yang lambat – perubahan harga yang tiba-tiba mungkin tidak tercermin hingga beberapa candlestick kemudian.

Wavelet Meyer diskrit adalah wavelet yang paling kompleks, dengan koefisien:[-0.015, -0.025, 0.0, 0.28, 0.52, 0.28, 0.0, -0.025, -0.015]。
Kode inti:
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线之前的中期趋势"
Fitur Utama:Ia memiliki koefisien terbanyak (9), data historis terpanjang, dan efek penghalusan terkuat. Ia cocok untuk mengekstrak “tren mingguan,” tetapi ada penundaan yang sangat besar - bahkan jika harga telah turun 10%, kurvanya mungkin masih menunjukkan “terus naik.”

Setelah meninjau tujuh jenis wavelet, Anda seharusnya telah memperhatikan sebuah pola:
Koefisien lebih banyak = lihat lebih lanjut = penghalusan lebih kuat = latensi lebih besar
Haar (2 koefisien) → Hanya melihat 1 batang → Hampir tidak halus Daubechies 4 (4 buah) → Lihat 3 sebelumnya → Sedikit halus Topi Meksiko (7) → Lihat 6 sebelumnya → Penghalusan sedang Meyer Diskrit (9) → Sebelum melihat 8 batang → Penghalusan berat
Efek dari bobot negatif adalah untuk meningkatkan sensitivitas dan mempermudah pendeteksian perubahan.
Haar/Morlet (tanpa bobot negatif) → Lembut dan halus, tidak sensitif Topi Meksiko (negatif di kedua ujung) → Sensitif terhadap titik infleksi Daubechies 4 (negatif) → Sensitif terhadap perubahan tren
Peran simetri = tidak ada distorsi = mempertahankan bentuk asli
Asimetri (Daubechies) → Dapat bergeser ke kiri/kanan Simetri (Biorthogonal/Meyer) → Mempertahankan posisi tengah
Transformasi wavelet dapat diterapkan secara rekursif, seperti boneka bersarang. Penerapan pertama disebut Level 1, menerapkannya lagi pada hasil Level 1 disebut Level 2, dan seterusnya.
Skala waktu yang terlihat pada berbagai tingkatan:
Dengan asumsi kita menggunakan grafik candlestick 1 jam untuk perdagangan BTC:
Level 1 → Amati fluktuasi jangka pendek selama 2-4 jam Level 2 → Amati tren selama 4-8 jam Level 3 → Amati tren jangka menengah selama 1-2 hari (strategi yang umum digunakan) Level 4 → Amati rentang harga 2-4 hari Level 5 → Amati tren utama selama 4-8 hari
Perbandingan hasil aktual:
Harga BTC asli (grafik 1 jam):99500, 99800, 99200, 100200, 99800, 100500, 100100, ...
Pemrosesan Level 1: 99600, 99650, 99500, 99900, 99950, 100200, 100250, … (Sedikit dihaluskan, tetapi fluktuasi masih terlihat)
Pemrosesan Level 3: 99620, 99650, 99700, 99800, 99950, 100100, 100200, … (Dihaluskan, menunjukkan tren jangka menengah)
Pemrosesan Level 5: 99630, 99640, 99660, 99700, 99760, 99840, 99930, … (Sangat halus, hanya menunjukkan arah umum)

Prinsip pemilihannya sederhana: gunakan Level yang sesuai berdasarkan periode kepemilikan Anda.
Scalping 15 menit → Level 1-2
Perdagangan intraday → Level 2-3
Lakukan latihan ayunan selama beberapa hari → Level 3-4
Analisis tren jangka panjang → Level 4-5
Penerapan transformasi wavelet dalam perdagangan sangat langsung: gunakan kurva harga yang dihaluskan yang dihasilkannya untuk menentukan arah tren, dan lakukan perdagangan ketika tren berubah. Secara spesifik, jika harga penutupan yang dihaluskan lebih tinggi dari harga sebelumnya, itu menunjukkan tren naik, jadi lakukan posisi beli (long); jika harga penutupan yang dihaluskan lebih rendah dari harga sebelumnya, itu menunjukkan tren turun, jadi tutup posisi atau lakukan posisi jual (short). Logika ini efektif karena wavelet telah menyaring fluktuasi acak jangka pendek, sehingga menyisakan “naik” atau “turun” sebagai probabilitas tinggi dari perubahan tren yang sebenarnya, bukan sinyal palsu yang disebabkan oleh noise.
# 执行小波变换
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 '空仓'},无需操作")

Tentu saja, dalam praktiknya, hal itu tidak sesederhana itu. Anda dapat menggunakan beberapa level wavelet secara bersamaan, seperti Level 2 yang menunjukkan tren jangka pendek dan Level 4 yang menunjukkan tren jangka panjang. Buka posisi hanya ketika keduanya bergerak ke arah yang sama, yang secara signifikan mengurangi sinyal palsu. Anda juga dapat menambahkan kondisi penyaringan lainnya, seperti mensyaratkan peningkatan volume perdagangan, volatilitas yang cukup tinggi, atau breakout harga di atas level kunci; semua ini dapat meningkatkan tingkat kemenangan. Untuk order stop-loss, Anda dapat mengaturnya secara dinamis menggunakan rentang fluktuasi harga yang dihaluskan wavelet; misalnya, stop-loss jika harga turun di bawah harga yang dihaluskan dikurangi 2 kali ATR. Dalam manajemen posisi, semakin jelas trennya (semakin curam kemiringan harga yang dihaluskan), semakin besar ukuran posisi; jika trennya tidak jelas, gunakan posisi yang lebih ringan atau tetap berada di luar pasar.
Namun ide intinya tetap sama: gunakan wavelet untuk mengubah harga yang berfluktuasi menjadi tren yang jelas, lalu buat penilaian berdasarkan tren yang jelas tersebut. Ini jauh lebih andal daripada melihat langsung kenaikan dan penurunan pada grafik candlestick asli, karena grafik candlestick asli mungkin naik 3% hari ini, turun 2% besok, dan naik 4% lusa. Anda tidak dapat membedakan apakah itu tren atau fluktuasi. Kurva yang diproses oleh wavelet akan memberi tahu Anda “tren keseluruhan selama periode ini adalah naik, meskipun ada fluktuasi di antaranya”.
Dalam hal efek penghalusan praktis, transformasi wavelet memang dapat berperan dalam pemrosesan data keuangan: ia dapat menyaring beberapa noise jangka pendek dan membantu mengekstrak informasi tren yang relatif jelas. Namun, teknik ini juga memiliki keterbatasan yang signifikan—Masalah lag tidak dapat dihindari sepenuhnya.Namun, metode ini hanya dapat memproses data historis dan tidak dapat memprediksi tren masa depan. Selain itu, efek penggunaan transformasi wavelet saja relatif terbatas; metode ini perlu dikombinasikan dengan metode analitik lain dan langkah-langkah pengendalian risiko untuk membangun sistem perdagangan yang lengkap.
Alasan utama keterbatasan ini terletak pada sifat unik pasar keuangan. Dalam bidang pemrosesan sinyal tradisional seperti pengenalan suara dan pemrosesan gambar, karakteristik derau relatif stabil, dan pola sinyal cenderung berulang. Oleh karena itu, transformasi wavelet dapat secara efektif memisahkan sinyal dari derau. Namun, pasar keuangan sangat berbeda: fluktuasi yang dianggap “derau” hari ini mungkin menjadi “sinyal” yang mencerminkan perubahan pasar besok; model analitis yang efektif sekarang mungkin menjadi tidak efektif di masa depan.Pasar itu sendiri bersifat tidak statis dan berubah secara dinamis.Tidak ada hukum yang tidak berubah dalam transformasi wavelet, yang mengharuskan penerapan transformasi wavelet di bidang keuangan harus disesuaikan secara fleksibel sesuai dengan lingkungan pasar tertentu.
Ketika Anda melihat seseorang melebih-lebihkan efek sebenarnya dari transformasi wavelet dan transformasi Fourier, cobalah mengajukan pertanyaan-pertanyaan ini: Jenis wavelet apa yang digunakan? Apa dasar pemilihan jenis ini dibandingkan jenis lainnya? Bagaimana tingkat penghalusannya ditetapkan? Apakah ada hasil pengujian balik dan prosedur pemilihan parameter yang sesuai?Mereka yang benar-benar memiliki pengetahuan profesional akan mampu menjelaskan detail teknis penting ini dengan jelas.
Berdasarkan pengetahuan kami yang terbatas, kami melakukan eksplorasi praktis ini.Ide intinya adalah untuk membagikan konsep aplikasi transformasi wavelet dengan cara yang sederhana dan mudah dipahami.Artikel ini bertujuan untuk membantu pembaca memperoleh pemahaman dasar tentang teknologi ini. Kami sangat menghargai para peneliti kuantitatif yang terlibat secara mendalam di bidang ini; jika Anda seorang ahli di bidang ini, Anda dipersilakan untuk menunjukkan kekurangan apa pun dalam artikel ini—seperti dasar teoritis untuk pemilihan parameter wavelet, metode optimasi untuk kombinasi multi-skala, dan jalur implementasi untuk pemilihan wavelet adaptif. Kami akan dengan rendah hati menerima saran Anda dan terus meningkatkan kontennya.
Fungsi plotting: Diterapkan pada mesin backtesting lokal penemu.
'''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: Diterapkan pada platform Penemu
'''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)