Komoditi Futures High Frequency Trading Strategy yang ditulis oleh C ++

Penulis:Kebaikan, Dicipta: 2020-05-22 15:28:11, Dikemas kini: 2023-11-02 19:54:28

img

Penny Jump Komoditi Futures High Frequency Trading Strategy yang ditulis oleh C++

Ringkasan

Pasaran adalah medan pertempuran, pembeli dan penjual sentiasa dalam permainan, yang juga merupakan tema kekal perniagaan perdagangan. Strategi Penny Jump yang dikongsi hari ini adalah salah satu strategi frekuensi tinggi, yang berasal dari pasaran pertukaran asing antara bank, dan sering digunakan dalam pasangan mata wang fakta arus perdana.

Klasifikasi strategi frekuensi tinggi

Dalam perdagangan frekuensi tinggi, terdapat dua jenis strategi utama. Strategi sisi pembeli dan strategi sisi penjual. Strategi sisi penjual biasanya merupakan strategi pembuatan pasaran, dan kedua-dua sisi strategi ini adalah lawan. Sebagai contoh, strategi pembeli arbitrase frekuensi tinggi untuk meratakan semua fenomena yang tidak munasabah di pasaran pada kelajuan terpantas, mengambil inisiatif untuk menyerang harga dengan cepat, atau makan harga yang salah dari pembuat pasaran lain.

Terdapat juga cara untuk menganalisis data sejarah atau peraturan pesanan pasaran, untuk menghantar pesanan yang belum selesai pada harga yang tidak munasabah terlebih dahulu, dan untuk menghantar pesanan pengeluaran dengan perubahan pesat harga pasaran. Strategi sedemikian adalah biasa dalam pembuatan pasaran pasif, setelah pesanan yang belum selesai dilaksanakan, dan selepas keuntungan tertentu atau selepas mencapai keadaan stop-loss, kedudukan akan ditutup. Strategi pembuatan pasaran pasif biasanya tidak memerlukan terlalu banyak kelajuan, tetapi ia memerlukan logika dan struktur strategi yang kuat.

Apakah strategi Penny Jump?

Penny Jump diterjemahkan ke dalam bahasa Inggeris adalah maksud kenaikan harga mikro. Prinsipnya adalah untuk mengesan harga beli dan harga jual pasaran. Kemudian, mengikut harga pasaran, ditambah atau dikurangkan kenaikan harga mikro harga penjejakan, adalah jelas bahawa ini adalah strategi perdagangan pasif, ia adalah milik pihak penjual strategi pembuatan pasaran. Model perniagaan dan logiknya adalah untuk menjalankan transaksi dua hala atas pesanan had yang disenaraikan di bursa untuk menyediakan kecairan.

Strategi pembuatan pasaran memerlukan jumlah inventori tertentu di tangan, dan kemudian berdagang di kedua-dua pihak pembeli dan penjual. Pendapatan utama strategi ini adalah pulangan yuran komisen yang disediakan oleh bursa, serta perbezaan harga yang diperoleh dengan membeli rendah dan menjual tinggi.

Prinsip strategi Penny Jump

Kita tahu bahawa terdapat banyak pelabur runcit di pasaran dagangan, dan terdapat juga banyak pelabur besar, seperti: hot money, dana awam, dana swasta, dan sebagainya. Pelabur runcit biasanya mempunyai lebih sedikit dana, pesanan mereka mempunyai kesan yang sangat kecil di pasaran, mereka boleh dengan mudah membeli dan menjual sasaran dagangan pada bila-bila masa. Tetapi untuk dana besar untuk mengambil bahagian dalam pasaran, ia tidak begitu mudah.

Jika pelabur besar ingin membeli 500 lot minyak mentah, tidak banyak pesanan pada harga semasa untuk dijual, dan pelabur tidak mahu membelinya pada harga yang lebih tinggi. Jika mereka bersikeras untuk menghantar pesanan pembelian pada harga semasa, kos titik slippage akan terlalu banyak. oleh itu, ia perlu menghantar pesanan menunggu pada harga yang dikehendaki. Semua peserta dalam pasaran akan melihat pesanan pembelian hugh yang menunjukkan pada harga tertentu.

Oleh kerana pesanan yang besar ini, ia kelihatan canggung di pasaran, kadang-kadang kita memanggilnya "pesanan gajah".

Selling Price 400.3, Order volume 50; buying price 400.1, Order volume 10. 

Tiba-tiba gajah yang rumit melompat ke pasaran, dan harga tawaran dihantar pada harga 400.1.

Selling Price 400.3, Order volume 50; Buying price 400.1, Order volume 510.

Semua peniaga tahu bahawa jika terdapat sejumlah besar pesanan menunggu pada harga tertentu, maka harga ini akan membentuk sokongan yang kuat ((atau rintangan).

Selling Price 400.3, Order volume 50; Buying price 400.2, Order volume 1,

harga 400.1 menjadi Buying 2 harga dalam kedalaman buku pesanan. Kemudian jika harga meningkat kepada 400.3, peniaga frekuensi tinggi akan memperoleh keuntungan sebanyak 0.1.

Walaupun harga tidak naik, dalam kedudukan beli 2, masih ada gajah yang memegang harga, dan ia boleh dengan cepat dijual kembali kepada gajah pada harga 400.1. Ini adalah idea umum strategi Penny Jump. Logiknya semudah ini, dengan memantau status pesanan pasaran, untuk membuat spekulasi mengenai niat lawan, dan kemudian memimpin dalam membina kedudukan yang menguntungkan, dan akhirnya mendapat keuntungan dari penyebaran kecil dalam jangka masa yang singkat. Untuk gajah ini, kerana dia menggantung sejumlah besar pesanan pembelian di pasaran, dia mendedahkan niat dagangnya, dan secara semula jadi menjadi sasaran yang diburu oleh pedagang frekuensi tinggi.

Penny Jump pelaksanaan strategi

Pertama, perhatikan peluang perdagangan dengan kebarangkalian yang sangat rendah di pasaran, dan buat strategi yang sesuai mengikut logik perdagangan. Jika logiknya rumit, anda perlu menggunakan pengetahuan matematik yang ada, gunakan model untuk menggambarkan sifat fenomena yang tidak rasional sebanyak mungkin, dan meminimumkan overfit. Di samping itu, ia mesti disahkan oleh enjin backtest yang boleh memenuhi prinsip Price first then Volume first. Mujurlah, kami mempunyai platform FMZ Quant yang kini menyokong mod backtesting ini.

Apakah maksud menyokong Price first then Volume first backtest engine? Anda boleh memahaminya sebagai: anda menghantar pesanan menunggu pada 400.1 untuk membeli, hanya apabila harga jual dalam kedalaman buku pesanan adalah 400.1 atau lebih rendah, pesanan menunggu anda boleh ditutup. Ia hanya mengira data harga pesanan yang menunggu, dan tidak mengira data jumlah pesanan yang menunggu, yang hanya memenuhi keutamaan harga ((harga pertama) dalam peraturan pencocokan pesanan pertukaran.

Volume first adalah versi yang dinaik taraf daripada price first. Ia adalah kedua-dua harga-keutamaan dan masa-pertama. Ia boleh dikatakan bahawa mod pencocokan ini adalah sama persis dengan model pertukaran. Dengan mengira jumlah pesanan yang belum selesai, ia dinilai sama ada pesanan yang belum selesai kini mencapai keadaan transaksi pasif untuk merealisasikan urus niaga jumlah, untuk mencapai simulasi sebenar persekitaran pasaran sebenar.

Di samping itu, sesetengah pembaca mungkin mendapati bahawa strategi Penny Jump memerlukan peluang perdagangan pasaran, iaitu keperluan pasaran mempunyai sekurang-kurangnya dua jurang harga hop. Dalam keadaan normal, kontrak perdagangan utama niaga hadapan komoditi agak sibuk. Perbezaan antara Beli 1 dan Jual 1 hop adalah bahawa hampir tidak ada peluang perdagangan. Oleh itu, kami meletakkan tenaga kami pada kontrak sub-utama di mana perdagangan tidak terlalu aktif. Jenis kontrak perdagangan ini kadang-kadang mempunyai dua atau bahkan tiga peluang hop. Sebagai contoh, dalam kontrak MA (kode Methanol dalam niaga hadapan komoditi Cina) 1909, situasi berikut berlaku:

img

Menjual 1 harga 2225 dengan jumlah 551, Membeli 1 harga 2223 dengan jumlah 565, melihat ke bawah selama beberapa saat. Selepas ini berlaku, ia akan hilang selepas beberapa tik. Dalam kes ini, kita menganggap pasaran sebagai pembetulan diri. Apa yang perlu kita lakukan adalah mengejar. Sebelum pasaran secara aktif memperbaikinya. jika kita melakukannya secara manual, ia adalah mustahil, dengan bantuan perdagangan automatik, kita boleh menjadikannya mungkin.

Dua hop situasi perbezaan harga kemunculan berlaku sangat kerap, tetapi tiga hop adalah yang paling selamat, tetapi tiga hop jarang berlaku, mengakibatkan kekerapan perdagangan terlalu rendah.

Seterusnya, kita memerhatikan perbezaan antara Selling 1 Buying 1 dan Buying 1 Selling 1 sekarang. Untuk mengisi jurang harga antara pasaran, jika kelajuan cukup cepat, ia boleh diletakkan di barisan hadapan pesanan lain. Juga, masa pegangan kedudukan sangat pendek, dengan logik perdagangan ini, selepas merealisasikan strategi, ambil MA909 sebagai contoh, ujian pasaran sebenar mengesyorkan Esunny bukannya antara muka CTP, mekanisme perubahan kedudukan dan keadaan dana untuk Esunny adalah dengan data yang didorong, sangat sesuai untuk perdagangan frekuensi tinggi.

Kod strategi

Selepas membersihkan logik perdagangan, kita boleh menggunakan kod untuk mencapainya. Oleh kerana platform FMZ Quant menggunakan contoh strategi penulisan C + + terlalu sedikit, di sini kita menggunakan C ++ untuk menulis strategi ini, yang mudah bagi semua orang untuk belajar, dan pelbagai adalah niaga hadapan komoditi.fmz.com> Login > Dashboard > perpustakaan strategi > Strategi baru > Klik menu drop-down di sudut kiri atas > Pilih C ++ untuk mula menulis strategi, memberi perhatian kepada komen dalam kod di bawah.

  • Langkah 1: Pertama membina kerangka strategi, di mana kelas HFT dan fungsi utama ditakrifkan. Barisan pertama dalam fungsi utama adalah untuk membersihkan log. Tujuan ini adalah untuk membersihkan maklumat log yang sebelumnya berjalan setiap kali strategi dimulakan semula. Barisan kedua adalah untuk menapis beberapa mesej ralat yang tidak diperlukan, seperti kelewatan rangkaian dan beberapa petua muncul, supaya log hanya merekodkan maklumat penting dan kelihatan lebih rapi; Barisan ketiga adalah untuk mencetak mesej Init OK, yang bermaksud bahawa program telah bermula. Barisan keempat adalah untuk membuat objek mengikut kelas HFT, dan nama objek adalah hft; barisan kelima program memasuki gelung sementara, dan selalu melaksanakan gelung objek dalam kaedah hft, dapat dilihat bahawa kaedah Loop adalah logik program ini. Barisan 6 adalah mesej teras. Di bawah keadaan lain, program tidak akan menjalankan garis 6, jika program telah berakhir, kaedah program tidak akan berjalan.

Seterusnya, mari kita lihat kelas HFT, yang mempunyai lima kaedah. Kaedah pertama adalah kaedah pembinaan; kaedah kedua adalah untuk mendapatkan hari semasa minggu untuk menentukan sama ada ia adalah garis K baru; kaedah ketiga adalah untuk membatalkan semua pesanan yang belum diisi, dan mendapatkan maklumat Kedudukan terperinci, kerana sebelum pesanan diletakkan, ia mesti terlebih dahulu menentukan status kedudukan semasa; kaedah keempat digunakan untuk mencetak beberapa maklumat, untuk strategi ini, kaedah ini bukan yang utama; yang paling penting adalah kaedah kelima, Kaedah ini terutamanya bertanggungjawab untuk memproses logik perdagangan dan meletakkan pesanan.

/ / Define the HFT class
Class HFT {
     Public:
         HFT() {
             // Constructor
         }
        
         Int getTradingWeekDay() {
             // Get the current day of the week to determine if it is a new K line
         }
        
         State getState() {
             / / Get order data
         }

         Void stop() {
             // Print orders and positions
         }
        
         Bool Loop() {
             // Strategy logic and placing orders
         }
};

// main function
Void main() {
     LogReset(); // clear the log
     SetErrorFilter("ready|timeout"); // Filter error messages
     Log("Init OK"); // Print the log
     HFT hft; // Create HFT object
     While (hft.Loop()); // enter loop
     Log("Exit"); // Program exits, prints the log
}

Oleh itu, mari kita lihat bagaimana setiap kaedah dalam kelas HFT ini dilaksanakan, dan bagaimana kaedah Loop yang paling teras berfungsi. Dari atas ke bawah, kita akan melaksanakan pelaksanaan khusus setiap kaedah satu demi satu, dan anda akan mendapati bahawa strategi frekuensi tinggi asal sangat mudah. Sebelum bercakap tentang kelas HFT, kita mula-mula menentukan beberapa pembolehubah global untuk menyimpan hasil pengiraan objek hft. Mereka adalah: menyimpan status pesanan, status kedudukan, memegang kedudukan panjang, memegang kedudukan pendek, harga beli, kuantiti membeli, harga jual, kuantiti jual. Sila lihat kod di bawah:

/ / Define the global enumeration type State
Enum State {
     STATE_NA, // store order status
     STATE_IDLE, // store position status
     STATE_HOLD_LONG, // store long position directions
     STATE_HOLD_SHORT, // store short position direction
};

/ / Define global floating point type variable
Typedef struct {
     Double bidPrice; // store the buying price
     Double bidAmount; // store the buying amount
     Double askPrice; // store the selling price
     Double askAmount; // store the selling amount
} Book;

Dengan pembolehubah global di atas, kita boleh menyimpan hasil yang dikira oleh objek hft secara berasingan, yang mudah untuk panggilan berikutnya oleh program. Seterusnya kita akan bercakap tentang pelaksanaan khusus setiap kaedah dalam kelas HFT. Pertama, kaedah HFT pertama adalah pembina yang memanggil kaedah getTradingWeekDay kedua dan mencetak hasilnya ke log. Kaedah getTradingWeekDay kedua mendapat hari semasa minggu untuk menentukan sama ada ia adalah garis K baru. Ia juga sangat mudah dilaksanakan, mendapatkan timestamp, mengira jam dan minggu, dan akhirnya mengembalikan bilangan minggu; kaedah getState ketiga agak panjang, saya hanya akan menerangkan idea umum, untuk penjelasan khusus, anda boleh melihat komen dalam blok pengekodan berikut.

Seterusnya, mari kita mendapatkan semua perintah terlebih dahulu, mengembalikan hasilnya adalah array biasa, kemudian melintasi array ini, satu demi satu untuk membatalkan pesanan, kemudian mendapatkan data kedudukan, mengembalikan array, dan kemudian melintasi Array ini, mendapatkan maklumat kedudukan terperinci, termasuk: arah, kedudukan, semalam atau kedudukan semasa, dan sebagainya, dan akhirnya mengembalikan hasilnya; kaedah berhenti keempat adalah untuk mencetak maklumat; kod adalah seperti berikut:

Public:
    // Constructor
    HFT() {
        _tradingDay = getTradingWeekDay();
        Log("current trading weekday", _tradingDay);
    }
    
    // Get the current day of the week to determine if it is a new K line
    Int getTradingWeekDay() {
        Int seconds = Unix() + 28800; // get the timestamp
        Int hour = (seconds/3600)%24; // hour
        Int weekDay = (seconds/(60*60*24))%7+4; // week
        If (hour > 20) {
            weekDay += 1;
        }
        Return weekDay;
    }
    
    / / Get order data
    State getState() {
        Auto orders = exchange.GetOrders(); // Get all orders
        If (!orders.Valid || orders.size() == 2) { // If there is no order or the length of the order data is equal to 2
            Return STATE_NA;
        }
        
        Bool foundCover = false; // Temporary variable used to control the cancellation of all unexecuted orders
        // Traverse the order array and cancel all unexecuted orders
        For (auto &order : orders) {
            If (order.Id == _coverId) {
                If ((order.Type == ORDER_TYPE_BUY && order.Price < _book.bidPrice - _toleratePrice) ||
                    (order.Type == ORDER_TYPE_SELL && order.Price > _book.askPrice + _toleratePrice)) {
                    exchange.CancelOrder(order.Id, "Cancel Cover Order"); // Cancel order based on order ID
                    _countCancel++;
                    _countRetry++;
                } else {
                    foundCover = true;
                }
            } else {
                exchange.CancelOrder(order.Id); // Cancel order based on order ID
                _countCancel++;
            }
        }
        If (foundCover) {
            Return STATE_NA;
        }
        
        // Get position data
        Auto positions = exchange.GetPosition(); // Get position data
        If (!positions.Valid) { // if the position data is empty
            Return STATE_NA;
        }

        // Traverse the position array to get specific position information
        For (auto &pos : positions) {
            If (pos.ContractType == Symbol) {
                _holdPrice = pos.Price;
                _holdAmount = pos.Amount;
                _holdType = pos.Type;
                Return pos.Type == PD_LONG || pos.Type == PD_LONG_YD ? STATE_HOLD_LONG : STATE_HOLD_SHORT;
            }
        }
        Return STATE_IDLE;
    }
    
    // Print orders and positions information
    Void stop() {
        Log(exchange.GetOrders()); // print order
        Log(exchange.GetPosition()); // Print position
        Log("Stop");
    }

Akhirnya, kita memberi tumpuan kepada bagaimana fungsi Loop mengawal logik strategi dan pesanan. Jika anda ingin melihat dengan lebih teliti, anda boleh merujuk kepada komen dalam kod. Pertama menentukan sama ada transaksi CTP dan pelayan pasaran disambungkan; kemudian mendapatkan baki akaun yang tersedia dan mendapatkan bilangan minggu; kemudian menetapkan kod pelbagai yang akan didagangkan, dengan memanggil fungsi rasmi FMZ SetContractType Quant, dan boleh menggunakan fungsi ini untuk mengembalikan butiran pelbagai dagangan; kemudian memanggil fungsi GetDepth untuk mendapatkan data kedalaman pasaran semasa. Data kedalaman termasuk: harga beli, jumlah beli, harga jual, jumlah jual, dan lain-lain, dan kami menyimpannya dengan pembolehubah, kerana mereka akan digunakan kemudian; Kemudian output data ini ke bar status untuk memudahkan pengguna untuk melihat status pasaran semasa; kod adalah seperti berikut:

// Strategy logic and placing order
Bool Loop() {
    If (exchange.IO("status") == 0) { // If the CTP and the quote server are connected
        LogStatus(_D(), "Server not connect ...."); // Print information to the status bar
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    If (_initBalance == 0) {
        _initBalance = _C(exchange.GetAccount).Balance; // Get account balance
    }
    
    Auto day = getTradingWeekDay(); // Get the number of weeks
    If (day != _tradingDay) {
        _tradingDay = day;
        _countCancel = 0;
    }
    
    // Set the futures contract type and get the contract specific information
    If (_ct.is_null()) {
        Log(_D(), "subscribe", Symbol); // Print the log
        _ct = exchange.SetContractType(Symbol); // Set futures contract type
        If (!_ct.is_null()) {
            Auto obj = _ct["Commodity"]["CommodityTickSize"];
            Int volumeMultiple = 1;
            If (obj.is_null()) { // CTP
                Obj = _ct["PriceTick"];
                volumeMultiple = _ct["VolumeMultiple"];
                _exchangeId = _ct["ExchangeID"];
            } else { // Esunny
                volumeMultiple = _ct["Commodity"]["ContractSize"];
                _exchangeId = _ct["Commodity"]["ExchangeNo"];
            }
            If (obj.is_null() || obj <= 0) {
                Panic("PriceTick not found");
            }
            If (_priceTick < 1) {
                exchange.SetPrecision(1, 0); // Set the decimal precision of the price and the quantity of the order.
            }
            _priceTick = double(obj);
            _toleratePrice = _priceTick * TolerateTick;
            _ins = _ct["InstrumentID"];
            Log(_ins, _exchangeId, "PriceTick:", _priceTick, "VolumeMultiple:", volumeMultiple); // print the log
        }
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    // Check orders and positions to set status
    Auto depth = exchange.GetDepth(); // Get depth data
    If (!depth.Valid) { // if no depth data is obtained
        LogStatus(_D(), "Market not ready"); // Print status information
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    _countTick++;
    _preBook = _book;
    _book.bidPrice = depth.Bids[0].Price; // "Buying 1" price
    _book.bidAmount = depth.Bids[0].Amount; // "Buying 1" amount
    _book.askPrice = depth.Asks[0].Price; // "Selling 1" price
    _book.askAmount = depth.Asks[0].Amount; // "Selling 1" amount
    // Determine the state of the port data assignment
    If (_preBook.bidAmount == 0) {
        Return true;
    }
    Auto st = getState(); // get the order data
    
    // Print the port data to the status bar
    LogStatus(_D(), _ins, "State:", st,
                "Ask:", depth.Asks[0].Price, depth.Asks[0].Amount,
                "Bid:", depth.Bids[0].Price, depth.Bids[0].Amount,
                "Cancel:", _countCancel,
                "Tick:", _countTick);
}

Setelah melakukan begitu banyak, kita akhirnya boleh meletakkan pesanan. Sebelum perdagangan, pertama kita menilai status kedudukan pegangan semasa program (tidak ada kedudukan pegangan, pesanan kedudukan panjang, pesanan kedudukan pendek), di sini kita menggunakan jika... jika... jika kawalan logik. Mereka sangat mudah, Jika tidak ada kedudukan pegangan, kedudukan akan dibuka mengikut keadaan logik. Jika ada kedudukan pegangan, kedudukan akan ditutup mengikut keadaan logik. Untuk memudahkan semua orang memahami, kita menggunakan tiga perenggan untuk menerangkan logika, Untuk bahagian kedudukan pembukaan:

Pertama mengisytiharkan pembolehubah Boolean, kita menggunakannya untuk mengawal kedudukan penutupan; seterusnya kita perlu mendapatkan maklumat akaun semasa, dan merakam nilai keuntungan, kemudian menentukan status pesanan pengeluaran, jika bilangan pengeluaran melebihi maksimum yang ditetapkan, cetak maklumat yang berkaitan dalam log; kemudian mengira nilai mutlak harga tawaran dan tawaran semasa perbezaan harga untuk menentukan sama ada terdapat lebih daripada 2 hops antara harga tawaran semasa dan harga meminta.

Seterusnya, kita mendapat harga Beli 1 dan harga Jual 1, jika harga pembelian sebelumnya lebih besar daripada harga pembelian semasa, dan jumlah jualan semasa kurang daripada jumlah pembelian, ini bermakna bahawa harga Beli 1 hilang. harga pembukaan kedudukan panjang dan kuantiti pesanan ditetapkan; sebaliknya, jika harga penjualan sebelumnya lebih rendah daripada harga penjualan semasa, dan jumlah pembelian semasa kurang daripada Jumlah penjualan membuktikan bahawa harga Jual 1 hilang, harga pembukaan kedudukan pendek dan kuantiti pesanan ditetapkan; pada akhirnya, kedudukan panjang dan pesanan pendek memasuki pasaran pada masa yang sama. Kod khusus adalah seperti berikut:

Bool forceCover = _countRetry >= _retryMax; // Boolean value used to control the number of closings
If (st == STATE_IDLE) { // if there is no holding position
    If (_holdAmount > 0) {
        If (_countRetry > 0) {
            _countLoss++; // failure count
        } else {
            _countWin++; // success count
        }
        Auto account = exchange.GetAccount(); // Get account information
        If (account.Valid) { // If get account information
            LogProfit(_N(account.Balance+account.FrozenBalance-_initBalance, 2), "Win:", _countWin, "Loss:", _countLoss); // Record profit value
        }
    }
    _countRetry = 0;
    _holdAmount = 0;
    
    // Judging the status of withdrawal
    If (_countCancel > _cancelMax) {
        Log("Cancel Exceed", _countCancel); // Print the log
        Return false;
    }

    Bool canDo = false; // temporary variable
    If (abs(_book.bidPrice - _book.askPrice) > _priceTick * 1) { // If there is more than 2 hops between the current bid and ask price
        canDo = true;
    }
    If (!canDo) {
        Return true;
    }
    
    Auto bidPrice = depth.Bids[0].Price; // Buying 1 price
    Auto askPrice = depth.Asks[0].Price; // Selling 1 price
    Auto bidAmount = 1.0;
    Auto askAmount = 1.0;
    
    If (_preBook.bidPrice > _book.bidPrice && _book.askAmount < _book.bidAmount) { // If the previous buying price is greater than the current buying price and the current selling volume is less than the buying volume
        bidPrice += _priceTick; // Set the opening long position price
        bidAmount = 2; // set the opening long position volume
    } else if (_preBook.askPrice < _book.askPrice && _book.bidAmount < _book.askAmount) { // If the previous selling price is less than the current selling price and the current buying volume is less than the selling volume
        askPrice -= _priceTick; // set the opening short position volume
        askAmount = 2; // set the opening short position volume
    } else {
        Return true;
    }
    Log(_book.bidPrice, _book.bidAmount, _book.askPrice, _book.askAmount); // Print current market data
    exchange.SetDirection("buy"); // Set the order type to buying long
    exchange.Buy(bidPrice, bidAmount); // buying long and open position
    exchange.SetDirection("sell"); // Set the order type to selling short
    exchange.Sell(askPrice, askAmount); // short sell and open position
}

Seterusnya, kita akan membincangkan bagaimana untuk menutup kedudukan panjang, pertama menetapkan jenis pesanan mengikut status kedudukan semasa, dan kemudian mendapatkan harga Jual 1. Jika harga Jual 1 semasa lebih besar daripada harga pembukaan membeli panjang, tetapkan harga kedudukan panjang penutupan. Jika harga Jual 1 semasa kurang daripada harga pembukaan kedudukan panjang, kemudian menetapkan semula pemboleh ubah kuantiti penutupan kepada benar, kemudian tutup semua kedudukan panjang. Bahagian pengekodan seperti di bawah:

Else if (st == STATE_HOLD_LONG) { // if holding long position
     exchange.SetDirection((_holdType == PD_LONG && _exchangeId == "SHFE") ? "closebuy_today" : "closebuy"); // Set the order type, and close position
     Auto sellPrice = depth.Asks[0].Price; // Get "Selling 1" price
     If (sellPrice > _holdPrice) { // If the current "selling 1" price is greater than the long position opening price
         Log(_holdPrice, "Hit #ff0000"); // Print long position opening price 
         sellPrice = _holdPrice + ProfitTick; // Set closing long position price
     } else if (sellPrice < _holdPrice) { // If the current "selling 1" price is less than the long position opening price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Sell(forceCover ? depth.Bids[0].Price : sellPrice, _holdAmount); // close long position
     If (!_coverId.Valid) {
         Return false;
     }
}

Akhirnya, mari kita lihat bagaimana untuk menutup kedudukan pendek. Prinsipnya adalah bertentangan dengan kedudukan panjang penutupan yang disebutkan di atas. Pertama, mengikut status kedudukan semasa, tetapkan jenis pesanan, dan kemudian dapatkan harga Beli 1, jika harga Beli 1 semasa kurang daripada harga pembukaan kedudukan pendek, harga kedudukan pendek penutupan akan ditetapkan. Jika harga Beli 1 semasa lebih besar daripada harga kedudukan pendek pembukaan, atur semula pemboleh ubah kuantiti penutupan menjadi benar, kemudian tutup semua kedudukan pendek.

Else if (st == STATE_HOLD_SHORT) { // if holding short position
     exchange.SetDirection((_holdType == PD_SHORT && _exchangeId == "SHFE") ? "closesell_today" : "closesell"); // Set the order type, and close position
     Auto buyPrice = depth.Bids[0].Price; // Get "buying 1" price
     If (buyPrice < _holdPrice) { // If the current "buying 1" price is less than the opening short position price
         Log(_holdPrice, "Hit #ff0000"); // Print the log
         buyPrice = _holdPrice - ProfitTick; // Set the close short position price
     } else if (buyPrice > _holdPrice) { // If the current "buying 1" price is greater than the opening short position price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Buy(forceCover ? depth.Asks[0].Price : buyPrice, _holdAmount); // close short position
     If (!_coverId.Valid) {
         Return false;
     }
}

Di atas adalah analisis lengkap mengenai strategi ini.https://www.fmz.com/strategy/163427) untuk menyalin kod sumber strategi lengkap tanpa mengkonfigurasi persekitaran backtest pada FMZ Quant.

Hasil ujian belakang

img

Logik Perdagangan

img

Kenyataan Strategi

Untuk memuaskan rasa ingin tahu perdagangan frekuensi tinggi dan untuk melihat hasilnya dengan lebih jelas, bayaran urus niaga persekitaran backtest strategi ini ditetapkan kepada 0, yang membawa kepada logik kelajuan cepat yang mudah. jika anda ingin menampung yuran urus niaga untuk mencapai keuntungan di pasaran sebenar. Lebih banyak pengoptimuman diperlukan. Seperti menggunakan aliran pesanan untuk menjalankan ramalan jangka pendek untuk meningkatkan kadar kemenangan, ditambah bayaran balik pertukaran, Untuk mencapai strategi yang menguntungkan yang mampan, terdapat banyak buku mengenai perdagangan frekuensi tinggi. Saya berharap semua orang dapat berfikir lebih banyak dan pergi ke pasaran sebenar dan bukannya hanya tinggal pada prinsipnya.

Mengenai kami

FMZ Quant adalah pasukan yang didorong oleh teknologi semata-mata yang menyediakan mekanisme backtest yang tersedia yang sangat cekap untuk peminat perdagangan kuantitatif.


Berkaitan

Lebih lanjut