Langkau tajuk talian

Asas Python untuk dagangan algo

Pedagang menggunakan Python untuk membina bot dagangan, indikator teknikal, plugin dan alat lain untuk membantu dagangan algo atau operasi manual, dan artikel ini menerangkan asas pengkodan dalam Python.

Python ialah bahasa pengaturcaraan tujuan umum yang popular, tahap tinggi yang digunakan untuk pembangunan web, sains data, automasi dan baru-baru ini, dagangan algoritma dalam cTrader. Sama ada anda mencipta bot dagangan berasaskan isyarat mudah atau strategi pelbagai indikator yang kompleks, Python menjadikan proses ini lebih cepat, lebih cekap dan lebih mudah diurus.

Algoritma Python dalam satu minit!

  • Alami sokongan Python terbina dalam dan akses lancar kepada API cTrader Algo, dengan cTrader menjadi satu-satunya platform utama yang menawarkan integrasi asli sedia ada. Tiada plugin, penyesuai atau persediaan kompleks diperlukan.
  • Fokus lebih kepada apa yang perlu dicapai oleh strategi anda kerana logik menjadi lebih mudah untuk disusun. Nikmati lelaran pantas, komponen boleh guna semula dan prestasi berskala.
  • Bangunkan dengan cepat, nyahpepijat dengan lebih bijak dan bekerjasama tanpa halangan. Kod anda akan sentiasa boleh disesuaikan, boleh dipercayai dan boleh diselenggarakan.
  • Akses dan manfaatkan beribu-ribu perpustakaan percuma/sumber terbuka, tutorial mendalam, sampel kod dan sokongan komuniti yang kuat di seluruh dunia.

Pemboleh ubah dan jenis data

Dalam Python, pemboleh ubah ditaip secara dinamik, yang bermaksud anda tidak perlu mengisytiharkan jenis data mereka secara eksplisit. Pentafsir menentukan jenis pada masa jalanan berdasarkan nilai yang ditetapkan.

Anda mencipta pemboleh ubah dengan hanya menetapkan nilai kepadanya:

1
2
3
4
price = 105.50         # float
enabled = True         # boolean
symbol = "EURUSD"      # string
orders = []            # empty list

Jenis data biasa

Jenis Penerangan Contoh
int Nombor bulat 5, 100, api.StepPips
float Nombor perpuluhan 1.1234, 100.5, api.Symbol.Ask
bool Nilai Boolean True, False
str Rentetan "EURUSD", api.Label
list Koleksi item [1, 2, 3], [p for p in api.Positions]

Dalam algoritma cTrader, pemboleh ubah menyimpan data penting berkaitan dengan maklumat pasaran, keputusan dagangan dan konfigurasi cBot. Pemboleh ubah ini sering mewakili volum dagangan yang dikira, nilai penunjuk, bendera Boolean, nama simbol, label dan banyak lagi.

Berikut ialah contoh:

1
2
3
4
class GridcBot():
    def on_start(self):
        self.volumeInUnits = api.Symbol.QuantityToVolumeInUnits(api.VolumeInLots)
        self.enoughMoney = True

Dalam kes ini,self.volumeInUnits ialah float yang digunakan untuk meletakkan pesanan, manakala self.enoughMoney ialah bool yang mengawal sama ada hendak terus membuka posisi dalam strategi grid.

Kelas dan objek

Python ialah bahasa pengaturcaraan berorientasikan objek (OOP), yang menyediakan alat untuk menyusun kod melalui kelas dan objek yang memodelkan entiti dan tingkah laku dunia sebenar. Kelas mentakrifkan cetak biru untuk mencipta objek, iaitu contoh kelas tersebut dengan data dan tingkah laku unik mereka sendiri. Konsep utama digariskan di bawah:

  • Kelas ditakrifkan menggunakan kata kunci class.
  • Kaedah __init__ (pembina) biasanya digunakan untuk memulakan keadaan objek.
  • Kaedah contoh mentakrifkan tingkah laku.
  • Atribut menyimpan data khusus untuk setiap objek.

Sebagai contoh, anda boleh mencipta kelas Car:

1
2
3
4
5
6
7
class Car:
    def __init__(self, color, speed):
        self.color = color
        self.speed = speed

    def accelerate(self):
        self.speed += 10

Kemudian anda boleh mencipta objek kelas Car dan berinteraksi dengannya:

1
2
3
my_car = Car("red", 50)
my_car.accelerate()
print(my_car.speed)  # This returns 60

Dalam konteks cTrader

Dalam cTrader, cBot, penunjuk dan plugin dilaksanakan sebagai kelas yang merangkumi keseluruhan logik mereka. Algo berinteraksi dengan platform cTrader menggunakan objek api khas yang menyediakan akses kepada simbol, carta, pesanan, penunjuk dan banyak lagi.

Anda boleh mencipta kelas SimplecBot dalam cTrader dengan cara ini:

1
2
3
class SimplecBot():
    def on_start(self):
        api.Print("cBot started")

Kelas SimplecBot termasuk satu kaedah (on_start(self)) yang dilaksanakan sekali apabila bot dagangan bermula. Fungsi api.Print menulis mesej ke log, menunjukkan bagaimana kaedah objek merangkumi tingkah laku dagangan.

Setiap contoh kelas secara berkesan mewakili algoritma dagangan yang tersendiri yang mengurus kitaran hayat dan keputusan dagangan sendiri menggunakan prinsip OOP. Dalam cBot cTrader standard, kelas mungkin menyimpan data keadaan dalaman, seperti volum, hasil penunjuk, dll., dan menggunakan beberapa kaedah untuk mengurus logik dagangan.

Pertimbangkan contoh lintasan MACD ini yang memulakan penunjuk MACD apabila dimulakan dan meletakkan pesanan beli apabila isyarat lintasan MACD berlaku:

1
2
3
4
5
6
7
class MACDCrossover():
    def on_start(self):
        self.macd = api.Indicators.MacdCrossOver(api.Source, api.LongCycle, api.ShortCycle, api.SignalPeriods)

    def on_bar_closed(self):
        if self.macd.MACD.Last(0) > self.macd.Signal.Last(0):
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, volume)

Kata kunci self

Di dalam kelas, self merujuk kepada contoh kelas dan menyediakan akses kepada pemboleh ubah dan kaedahnya. self digunakan untuk:

  • Menyimpan data seperti hasil penunjuk, volum posisi dan nilai konfigurasi.
  • Menjejaki keadaan dalaman merentasi panggilan kaedah yang berbeza seperti on_start(), on_tick() atau on_bar_closed().

Contoh ini menunjukkan bagaimana self digunakan:

1
2
3
4
class MACDCrossover():
    def on_start(self):
        self.volume = api.Symbol.QuantityToVolumeInUnits(api.VolumeInLots)
        self.macd = api.Indicators.MacdCrossOver(api.Source, api.LongCycle, api.ShortCycle, api.SignalPeriods)

Dalam kes ini,self.volume menyimpan volum yang dikira untuk digunakan untuk dagangan, manakala self.macd menyimpan objek penunjuk MACD, membolehkan akses kepada nilainya sepanjang kitaran hayat cBot. Tanpa self, pemboleh ubah ini akan menjadi tempatan kepada on_start() dan tidak boleh diakses dalam on_bar_closed() di mana keputusan dagangan mungkin dibuat.

Kaedah dan fungsi

Fungsi ialah blok kod boleh guna semula yang digunakan untuk melaksanakan tugas tertentu. Apabila fungsi ditakrifkan di dalam kelas, ia dipanggil kaedah, dan ia beroperasi pada keadaan dalaman kelas melalui parameter self. Dalam konteks dagangan algoritma dengan cTrader, kaedah mentakrifkan bagaimana algoritma dagangan anda bertindak dalam keadaan yang berbeza, seperti tik pasaran, penutupan bar atau permulaan.

Platform secara automatik memanggil kaedah khas (dikenali sebagai pengendali acara) pada masa yang sesuai, seperti:

on_start(self) – dipanggil sekali apabila bot dimulakan.

1
2
def on_start(self):
    api.Print("cBot started")

on_tick(self) – dipanggil pada setiap tik pasaran yang masuk.

1
2
def on_tick(self):
    api.Print("Tick received")

on_bar_closed(self) – dipanggil apabila lilin/bar baharu ditutup (sesuai untuk strategi berasaskan masa).

1
2
3
4
def on_bar_closed(self):
    if Functions.HasCrossedAbove(...):
        self.close_positions(TradeType.Sell)
        api.ExecuteMarketOrder(...)

Kaedah tersuai atau pembantu

Untuk mengelakkan penulisan semula dan penduaan kod, anda boleh mentakrifkan kaedah anda sendiri. Kaedah tersuai sedemikian harus merangkumi logik biasa yang mungkin digunakan semula oleh robot dagangan anda.

Kaedah di bawah mengembalikan semua posisi terbuka yang dikaitkan dengan label cBot semasa, menjadikannya mudah untuk menjejak atau menutup posisi secara konsisten.

1
2
def get_bot_positions(self):
    return api.Positions.FindAll(api.Label)

Pertimbangkan kaedah lain yang mengira jarak dalam pip antara harga semasa dan entri posisi, yang penting untuk keputusan dalam strategi berasaskan grid.

1
2
def get_distance_in_pips(self, position):
    return (position.EntryPrice - api.Symbol.Ask if position.TradeType == TradeType.Buy else api.Symbol.Bid - position.EntryPrice) / api.Symbol.PipSize

Setelah kaedah ditakrifkan, anda boleh memanggilnya dari dalam kelas yang sama menggunakan kata kunci self. Pendekatan ini membolehkan anda menggunakan semula logik di mana-mana dalam bot anda tanpa menduakan kod.

Sebagai contoh, selepas mentakrifkan get_bot_positions(), anda mungkin memanggilnya di dalam kaedah lain untuk menutup semua posisi:

1
2
3
4
def close_positions(self, tradeType):
    for position in self.get_bot_positions():   # Helper method call
        if position.TradeType == tradeType:
            api.ClosePosition(position)

Di sini, self.get_bot_positions() memanggil kaedah pembantu, mengembalikan hanya posisi yang dikaitkan dengan label bot semasa.

Begitu juga, kaedah get_distance_in_pips() boleh digunakan semula untuk membuat keputusan dagangan. Sebagai contoh, dalam strategi grid, anda mungkin mahu membuka pesanan baharu hanya jika pasaran telah bergerak cukup jauh dari posisi terakhir:

1
2
3
4
5
6
7
def on_tick(self):
    grid_positions = self.get_bot_positions()
    if len(grid_positions) > 0:
        position_with_highest_pips = sorted(grid_positions, key=lambda pos: pos.Pips, reverse=True)[0]
        distance = self.get_distance_in_pips(position_with_highest_pips)  # Helper method call
        if distance >= api.StepPips:
            self.open_position()

Konsep lain

Ruang nama dan import

Ruang nama dalam Python membantu menyusun kod dan mengelakkan perlanggaran nama dengan mengumpulkan pengecam berkaitan (pemboleh ubah, fungsi, kelas). Import membolehkan anda membawa masuk modul, pustaka atau pakej luaran untuk memperluaskan fungsi melampaui ciri standard Python.

Dalam Python, anda boleh mengimport modul standard atau pakej tersuai:

1
2
import math
print(math.sqrt(16))  # 4.0

Anda juga boleh mengimport fungsi atau kelas tertentu:

1
2
from math import sqrt
print(sqrt(25))  # 5.0

Apabila menulis algoritma untuk cTrader dalam Python, import berfungsi sedikit berbeza kerana cTrader berintegrasi dengan API cTrader Algo berasaskan .NET. Persediaan ini melibatkan jambatan yang membolehkan kod Python berinteraksi dengan himpunan .NET, dan ini menjelaskan mengapa cBot biasa bermula dengan:

1
2
3
4
5
6
7
8
9
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *

# Import trading wrapper functions
from robot_wrapper import *

Di mana:

  • import clr memuatkan Common Language Runtime (CLR), membolehkan Python beroperasi dengan pustaka .NET.
  • clr.AddReference("cAlgo.API") merujuk kepada himpunan API cAlgo, yang mengandungi semua kelas, kaedah dan objek berkaitan dagangan.
  • from cAlgo.API import * membawa masuk semua jenis dari API (contohnya, TradeType, Color, Position).
  • from robot_wrapper import * memuatkan fungsi pembantu dan pembungkus yang memudahkan operasi dagangan biasa.

Sistem ruang nama memastikan bahawa:

  • Nama terbina dalam Python (seperti print) mengelakkan konflik dengan nama cTrader (seperti api.Print).
  • Semua objek khusus dagangan (api.Symbol, api.Indicators, api.ExecuteMarketOrder) berasal dari ruang nama API cTrader Algo, menjadikannya tersusun dan berbeza.
  • Anda boleh memperluaskan fungsi dengan mengimport pakej tersuai anda sendiri untuk bekerja bersama jenis terbina dalam cTrader.

Gelung

Gelung membolehkan anda mengulangi operasi ke atas urutan nilai atau sehingga syarat dipenuhi. Dalam dagangan algoritma, gelung sering digunakan untuk memproses posisi (contohnya, menutup, menapis atau mengemaskini), memeriksa syarat merentasi pelbagai aset atau indikator, melaksanakan strategi grid atau martingale yang memerlukan penempatan pesanan berulang dan banyak lagi.

Dalam Python, lelaran adalah mudah dan menyokong kedua-dua gelung for (untuk lelaran melalui koleksi) dan gelung while (untuk mengulangi sehingga syarat berubah).

Anda boleh menulis gelung untuk menutup posisi:

1
2
3
4
def close_positions(self, tradeType):
    for position in self.get_bot_positions():
        if position.TradeType == tradeType:
            api.ClosePosition(position)

Dalam kes ini:

  • self.get_bot_positions() mengembalikan semua posisi yang dimiliki oleh cBot semasa.
  • Gelung for melalui setiap posisi.
  • Posisi yang sepadan ditutup dengan api.ClosePosition.

Pertimbangkan gelung berbeza yang mengulangi semua posisi grid terbuka, menutupnya satu demi satu dan secara rekursif memeriksa jika ada posisi yang masih ada (keselamatan sekiranya berlaku penutupan separa).

1
2
3
4
5
6
def close_grid_positions(self):
    for position in self.get_grid_positions():
        position.Close()

    if len(self.get_grid_positions()) > 0:
        self.close_grid_positions()

Penyata bersyarat

Kenyataan bersyarat mengawal aliran pelaksanaan dalam Python dengan membolehkan algoritma anda membuat keputusan berdasarkan ungkapan logik. Syarat adalah tulang belakang logik strategi, menentukan bila untuk memasuki, keluar atau menguruskan posisi.

Python menyokong tiga binaan bersyarat utama:

  • if – melaksanakan kod apabila syarat adalah benar.
  • elif (else if) – memeriksa syarat lain jika syarat pertama adalah palsu.
  • else – menyediakan pilihan terakhir apabila tiada syarat dipenuhi.

Pertimbangkan syarat lintasan MACD yang dinyatakan dalam kod ini:

1
2
3
4
if self.macd.MACD.Last(0) > self.macd.Signal.Last(0):
    api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, self.volumeInUnits, api.Label, api.StopLossInPips, api.TakeProfitInPips)
elif self.macd.MACD.Last(0) < self.macd.Signal.Last(0):
    api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, self.volumeInUnits, api.Label, api.StopLossInPips, api.TakeProfitInPips)

Struktur ini:

  • Membuat pesanan beli apabila garis MACD berada di atas garis isyarat.
  • Membuat pesanan jual apabila garis MACD berada di bawah garis isyarat.
  • Melangkau dagangan jika tiada isyarat yang jelas.

Senarai

Python menyediakan alat yang berkuasa dan ringkas untuk bekerja dengan koleksi data, seperti dagangan, harga atau indikator. Dua yang paling biasa adalah pemahaman senarai dan fungsi pengagregatan terbina dalam seperti sum().

Sebagai contoh, anda boleh menulis kod yang mengulangi numbers dan hanya menyimpan nombor genap dengan cara ini:

1
2
numbers = [1, 2, 3, 4, 5]
squares = [n**2 for n in numbers if n % 2 == 0]

Anda boleh menggunakan pemahaman senarai untuk memilih hanya posisi untuk simbol semasa, menghasilkan senarai yang ditapis yang berguna dalam persekitaran pelbagai simbol.

1
positions = [p for p in api.Positions if p.SymbolName == api.SymbolName]

Mengagregat keuntungan atau volum menggunakan sum() adalah pendekatan standard dalam strategi dagangan grid untuk menentukan bila jumlah keuntungan memenuhi sasaran.

1
net_profit_sum = sum([p.NetProfit for p in grid_positions])

Anda boleh menggabungkan penapisan dan pengagregatan dengan cara ini:

1
2
buy_positions = [p for p in api.Positions if p.TradeType == TradeType.Buy]
avg_buy_price = sum([p.EntryPrice * p.VolumeInUnits for p in buy_positions]) / sum([p.VolumeInUnits for p in buy_positions])

Operasi segerak dan tak segerak

Python mengikuti model pelaksanaan segerak secara lalai. Kaedah kitaran hayat algoritma anda, seperti on_start, on_tick dan on_bar_closed, dicetuskan oleh gelung peristiwa platform, satu demi satu.

Berikut adalah perwakilan asas aliran dagangan segerak:

graph TD
    A(Menemui isyarat) ==> B(Melaksanakan pesanan)
    B ==> C(Posisi mencapai TP/SL)
    C ==> D(Tutup posisi)
    D ==> A

Dalam aliran segerak, sebarang operasi yang berjalan lama boleh menyekat bebenang, berpotensi melambatkan peristiwa seterusnya. Walau bagaimanapun, dalam strategi dunia sebenar, algoritma biasanya memulakan tindakan tidak menyekat, seperti menghantar pesanan atau menetapkan henti rugi dan ambilan untung, kemudian menunggu peristiwa masa depan (seperti tik atau bar baharu) untuk mengendalikan hasil. Persediaan ini menghasilkan penyelarasan seperti tak segerak, walaupun binaan async/await Python tidak digunakan.

Nota

Bagi kebanyakan algoritma dagangan, pengaturcaraan tak segerak yang jelas tidak diperlukan.

cTrader menguruskan keserentakan dengan menyusun panggilan balik berasaskan peristiwa anda. Setiap kaedah dipanggil secara bebas dan tidak pernah selari, menghapuskan keperluan untuk perlindungan berbilang bebenang. Reka bentuk ini membolehkan strategi bertindak balas kepada pelbagai keadaan dagangan sekaligus, dalam erti kata logik, tanpa menyekat.

Dalam contoh di bawah, strategi menilai isyarat beli dan jual secara bebas dan bertindak balas sewajarnya, tanpa sebarang pertindihan dalam konteks pelaksanaan.

graph TD
    A([Mengesan isyarat]) ==> B([Buka pesanan beli]) & C([Buka pesanan jual untuk <br>lindung nilai]) ==> D([Pesanan mencapai<br>take profit atau stop loss])
    D ==> E([Tutup posisi])
    E ==> A

Walaupun keputusan mungkin kelihatan selari, ia dikendalikan secara berurutan oleh sistem penggiliran dalaman cTrader. Seni bina platform bertujuan untuk mencegah isu keserentakan sambil mengekalkan robot dagangan responsif terhadap perubahan pasaran.

Image title