Membuat fungsi sendiri
Membagi kode menjadi perhitungan bernama dan menggunakannya di beberapa tempat.
Kamu sudah mengenal perhitungan ukuran candle: high - low. Jika dibutuhkan dalam beberapa perhitungan, kamu bisa menempatkannya dalam fungsi sendiri. Pemanggilannya bisa menjelaskan tujuan perhitungan, sementara rumusnya tetap disimpan di satu tempat.
Input dan hasil sebuah fungsi
def price_range(top: float, bottom: float) -> float:
return top - bottomdef mendefinisikan fungsi. Nama fungsinya price_range. Fungsi mengharapkan dua input bernama top dan bottom. Keduanya angka yang boleh memiliki pecahan.
-> float menandakan tipe hasil. return menghitung dan mengembalikan hasil, lalu mengakhiri pemanggilan fungsi tersebut.
Hasil price_range(105, 100) adalah 5. Fungsi tidak mengetahui apakah angka tersebut harga dan tidak memilih candle. Pemanggillah yang memberikan kedua nilai.
Isi fungsi di sini menjorok empat spasi. Dalam contoh ini, definisi berada di tingkat terluar file, sejajar dengan main(). Karena itu, kedua harga yang dibutuhkan diberikan sebagai parameter. Fungsi juga bisa dibuat di dalam main(); kita akan mencobanya di bawah.
Cakupan nama
top dan bottom adalah parameter yang hanya tersedia di dalam fungsi price_range. main() tidak bisa merujuknya secara langsung. Di sana, kamu menggunakan hasil yang dikembalikan.
Cakupan nama menentukan bagian kode tempat nama itu dapat diakses. Dua fungsi berbeda boleh menggunakan nama parameter yang sama tanpa membuat parameternya menjadi satu variabel bersama.
price_range yang didefinisikan pada tingkat terluar file tidak otomatis dapat mengakses variabel lokal main(). Namun, fungsi ini bisa menggunakan nama yang diimpor di awal file, seperti close. Jadi, tempat fungsi didefinisikan juga memengaruhi nama yang dapat dilihatnya.
Definisi dan pemanggilan fungsi juga berbeda. Definisi menentukan aturan; pemanggilan menjalankan aturan tersebut dengan nilai tertentu.
Program lengkap
Buat file price_functions.py. Fungsi yang sama menghitung seluruh rentang candle serta perubahan bertanda antara harga pembukaan dan penutupan:
"""
@pyne edge
"""
from pynecore.lib import close, color, high, low, open, plot, script
def price_range(top: float, bottom: float) -> float:
return top - bottom
@script.indicator("Price Functions", overlay=False)
def main():
full_range = price_range(high, low)
body_change = price_range(close, open)
plot(full_range, "Full range", color=color.blue)
plot(body_change, "Body change", color=color.orange)Jalankan pada data demo. Rentang penuh tidak negatif karena harga tertinggi candle setidaknya sama dengan harga terendah. Perubahan antara pembukaan dan penutupan bisa negatif. Fungsi tidak mengubah harga yang diberikan; fungsi mengembalikan selisih kedua angka.

Fungsi contoh ini pendek dan mudah diperiksa secara manual. Dalam program yang lebih besar, kamu juga bisa memberi nama pada subperhitungan yang lebih rumit, tetapi satu penjumlahan tidak harus dijadikan fungsi tersendiri.
Urutan parameter
Pemanggilan price_range(high, low) memberikan nilai high kepada top dan nilai low kepada bottom. Jika urutannya ditukar, tanda hasil pengurangan juga berbalik.
Kamu juga bisa menyebutkan nama parameternya:
full_range = price_range(top=high, bottom=low)Cara ini lebih panjang, tetapi bisa memudahkan pembacaan pemanggilan yang lebih rumit. Nama yang diberikan harus sama persis dengan nama parameter fungsi.
Fungsi di dalam main()
Fungsi yang didefinisikan di dalam fungsi lain juga bisa mengakses variabel fungsi yang mengelilinginya. Ini berguna ketika beberapa perhitungan menggunakan pengaturan input yang sama.
Kita akan menghaluskan kedua garis program sebelumnya dengan moving average. Panjang rata-rata ditentukan melalui satu input dan digunakan oleh kedua perhitungan. Fungsi di dalam hanya menerima dua harga; panjangnya dibaca dari parameter main().
Dalam price_functions.py, pertahankan fungsi luar price_range dan dekorator indikator. Tambahkan input dan ta pada impor dari pynecore.lib, lalu ganti definisi main() dengan:
def main(
length: int = input.int(5, title="Average length", minval=1, maxval=200),
):
def average_difference(top: float, bottom: float) -> float:
return ta.sma(price_range(top, bottom), length)
average_range = average_difference(high, low)
average_body_change = average_difference(close, open)
plot(average_range, "Average range", color=color.blue)
plot(average_body_change, "Average body change", color=color.orange)length adalah input bilangan bulat yang sudah kita kenal. Fungsi dalam average_difference menerima dua parameter: top dan bottom diberikan oleh pemanggilan. Nilai length dibaca dari fungsi main() yang mengelilinginya, sehingga tidak perlu diberikan lagi pada setiap pemanggilan.
Definisi fungsi dalam diawali empat spasi karena merupakan bagian main(). Isinya sendiri, baris return, diawali delapan spasi. Nama average_difference dapat digunakan di dalam main() dan tidak tersedia di tingkat terluar file.
price_range menghitung selisih kedua harga dan ta.sma mengembalikan moving average selisih itu. Garis biru menunjukkan rata-rata seluruh rentang candle, sedangkan garis oranye menunjukkan rata-rata perubahan bertanda antara harga pembukaan dan penutupan. Kedua pemanggilan berjalan pada setiap candle, sehingga kedua rata-rata dihitung terus-menerus.
Jalankan program yang diubah, lalu buka Inputs melalui ikon roda gigi. Ubah Average length dari 5 menjadi 20 dan klik Save. Grafik yang terbuka otomatis dihitung ulang dan kedua garis menggunakan rata-rata dua puluh candle. Kamu tidak perlu mengubah kedua pemanggilan fungsi dalam. Jika panjang diatur menjadi 1, kedua garis program asli muncul kembali.
Akses ke variabel luar ini disebut closure. Membaca nilai tidak berarti penugasan di dalam fungsi otomatis bisa menimpa variabel luar. Dalam contoh ini, kita hanya membaca nilai length.
Jika membaca kode hasil terjemahan Pine Script: PyneComp membuat fungsi di dalam main(). Variabel yang dibuat di tingkat utama Pine Script juga ditempatkan di dalam main(), sehingga fungsi dalam bisa mengaksesnya. Karena itu, susunan ini terlihat dalam kode hasil terjemahan. Saat menulis Pyne code sendiri, kamu bisa menggunakan kedua cara: fungsi terpisah yang menerima parameter dan fungsi dalam yang juga mengakses variabel di sekelilingnya.
Pada versi berparameter, semua nilai yang diberikan terlihat dari pemanggilan dan fungsi yang sama mudah digunakan dengan pasangan harga lain. Fungsi dalam dapat lebih nyaman ketika beberapa perhitungan bergantung pada variabel yang sama dalam main().
Fungsi buatan juga bisa memiliki status
price_range hanya menghitung dari nilai yang diterima. Fungsi ini tidak menyimpan variabel antarcandle dan tidak menggunakan riwayat. Karena itu, kamu bisa memanggilnya kapan saja dengan dua nilai.
Sebaliknya, average_difference di atas menggunakan status karena ta.sma di dalamnya menghitung berdasarkan nilai terdahulu. Kamu juga bisa membuat variabel Persistent atau Series langsung dalam fungsi sendiri.
Fungsi penghitung peristiwa
Kita akan menghitung candle naik dan turun secara terpisah. Untuk itu, kita menulis fungsi yang menerima nilai logika dan mengingat berapa kali nilai benar sudah diterimanya.
Impor nama Persistent di awal file:
from pynecore import PersistentTulis fungsi berikut sebelum main(), pada tingkat terluar file:
def count_events(event: bool) -> int:
count: Persistent[int] = 0
if event:
count += 1
return countNilai awal count adalah nol. Jika event benar, nilainya bertambah satu; jika salah, nilainya dipertahankan. Dalam kedua kasus, return mengembalikan total sejauh ini. Setelah pemanggilan fungsi berakhir, nilai variabel Persistent tetap tersimpan untuk pemanggilan berikutnya.
Pertahankan overlay=False. Ganti definisi dan isi main() sebelumnya dengan:
def main():
bullish_count = count_events(close > open)
bearish_count = count_events(close < open)
plot(bullish_count, "Bullish count", color=color.green)
plot(bearish_count, "Bearish count", color=color.red)Kita memanggil fungsi yang sama dari dua tempat berbeda dalam kode. Setiap lokasi pemanggilan memiliki status count tersendiri: yang pertama menghitung candle naik, yang kedua menghitung candle turun. Pemanggilan pertama tidak menambah penghitung pemanggilan kedua.
Misalnya, jika empat candle pertama mengikuti urutan ini, hasilnya sebagai berikut:
| Candle | Hubungan harga pembukaan dan penutupan | bullish_count | bearish_count |
|---|---|---|---|
| Pertama | Harga penutupan lebih tinggi | 1 | 0 |
| Kedua | Harga penutupan lebih rendah | 1 | 1 |
| Ketiga | Kedua harga sama | 1 | 1 |
| Keempat | Harga penutupan lebih tinggi | 2 | 1 |
Jalankan pada data demo. Garis hijau hanya bertambah pada candle naik, sedangkan garis merah hanya pada candle turun. Eksekusi baru membangun kedua penghitung kembali dari nol.
Kedua pemanggilan fungsi berjalan pada setiap candle; kondisi penambahan ada di dalam fungsi. Untuk fungsi yang menggunakan status, urutan dan frekuensi pemanggilan merupakan bagian dari perilakunya. Jika fungsi hanya dipanggil pada sebagian candle, riwayat di dalamnya juga hanya bergerak pada pemanggilan tersebut.
Jika memerlukan satu penghitung bersama, panggil fungsi sekali lalu gunakan variabel hasilnya di beberapa tempat. Lokasi pemanggilan kedua berarti penghitung terpisah yang baru.
Beberapa pernyataan dalam satu fungsi
Jika hasil memerlukan nilai antara, kamu bisa menghitungnya sebelum return:
def midpoint(top: float, bottom: float) -> float:
total = top + bottom
return total / 2total adalah variabel lokal. Variabel ini tidak menjadi variabel main() setelah pemanggilan selesai. Kita hanya mengembalikan hasil dari fungsi.
Coba sendiri
Tambahkan fungsi midpoint ke program, lalu buat indikator overlay yang menggambar titik tengah harga candle. Gunakan parameter top dan bottom untuk menerima harga tertinggi dan terendah.
Solusi latihan
Tulis definisi midpoint di atas sebelum main(). Gunakan overlay=True pada dekorator indikator, dengan isi:
center = midpoint(high, low)
plot(center, "Midpoint", color=color.blue, linewidth=2)Perhitungan dan gambar dua garis sebelumnya bisa dihapus dari versi ini. Hapus juga impor yang tidak digunakan.
Menjelaskan sebuah pemanggilan
Untuk baris price_range(close, open), jelaskan nilai yang masuk ke setiap parameter, apa yang terjadi pada baris return, dan di mana main() menerima hasilnya. Ketiga langkah ini juga bisa kamu telusuri dalam pemanggilan fungsi yang lebih panjang.