Pasar adalah medan perang, pembeli dan penjual selalu dalam permainan, yang juga merupakan tema abadi dari bisnis perdagangan.
Dalam perdagangan frekuensi tinggi, ada dua jenis strategi utama. Strategi sisi pembeli dan strategi sisi penjual. Strategi sisi penjual biasanya merupakan strategi pembuatan pasar, dan kedua sisi strategi ini adalah lawan. Misalnya, strategi pembeli arbitrase frekuensi tinggi untuk meratakan semua fenomena yang tidak wajar di pasar dengan kecepatan tercepat, mengambil inisiatif untuk menyerang harga dengan cepat, atau makan harga yang salah dari pembuat pasar lainnya.
Ada juga cara untuk menganalisis data historis atau aturan pemesanan pasar, untuk mengirim pesanan tertunda dengan harga yang tidak masuk akal sebelumnya, dan untuk mengirim pesanan penarikan dengan perubahan harga pasar yang cepat. Strategi semacam itu umum dalam pembuatan pasar pasif, setelah pesanan tertunda dieksekusi, dan setelah keuntungan tertentu atau setelah mencapai kondisi stop-loss, posisi akan ditutup. Strategi pembuatan pasar pasif biasanya tidak memerlukan terlalu banyak kecepatan, tetapi membutuhkan logika dan struktur strategi yang kuat.
Penny Jump diterjemahkan ke dalam bahasa Inggris adalah arti dari kenaikan harga mikro. Prinsipnya adalah untuk melacak harga beli dan harga jual pasar. Kemudian, sesuai dengan harga pasar, ditambah atau dikurangi kenaikan harga mikro dari harga pelacakan, jelas bahwa ini adalah strategi perdagangan pasif, itu milik strategi pembuatan pasar sisi penjual. Model bisnis dan logisannya adalah untuk melakukan transaksi bilateral pada pesanan batas yang terdaftar di bursa untuk memberikan likuiditas.
Strategi pembuatan pasar membutuhkan jumlah persediaan tertentu di tangan, dan kemudian diperdagangkan baik di sisi pembeli maupun penjual. Pendapatan utama dari strategi ini adalah pengembalian biaya komisi yang disediakan oleh bursa, serta perbedaan harga yang diperoleh dengan membeli rendah dan menjual tinggi.
Kami tahu bahwa ada banyak investor ritel di pasar perdagangan, dan juga ada banyak investor besar, seperti:
Jika investor besar ingin membeli 500 lot minyak mentah, tidak ada begitu banyak pesanan dengan harga saat ini untuk dijual, dan investor tidak ingin membelinya dengan harga yang lebih tinggi. Jika mereka bersikeras untuk mengirim pesanan pembelian dengan harga saat ini, Biaya titik slippage akan terlalu tinggi. oleh karena itu, ia harus mengirim pesanan yang sedang menunggu dengan harga yang diinginkan. Semua peserta di pasar akan melihat pesanan pembelian hugh yang menunjukkan harga tertentu.
Karena pesanan yang sangat besar, itu terlihat canggung di pasar, kadang-kadang kita menyebutnya "pesanan gajah".
Selling Price 400.3, Order volume 50; buying price 400.1, Order volume 10.
Tiba-tiba gajah yang rumit ini melompat ke pasar, dan harga penawaran dikirim pada harga 400.1.
Selling Price 400.3, Order volume 50; Buying price 400.1, Order volume 510.
Pedagang semua tahu bahwa jika ada sejumlah besar pesanan yang tertunda pada harga tertentu, maka harga ini akan membentuk support (atau resistance) yang kuat.
Selling Price 400.3, Order volume 50; Buying price 400.2, Order volume 1,
harga 400.1 menjadi
Bahkan jika harga tidak naik, dalam posisi
Pertama, amati peluang perdagangan dengan probabilitas pasar yang sangat rendah, dan buat strategi yang sesuai sesuai dengan logika perdagangan. Jika logika itu kompleks, Anda perlu menggunakan pengetahuan matematika yang ada, gunakan model untuk menggambarkan sifat fenomena irasional sebanyak mungkin, dan meminimalkan overfit. Selain itu, itu harus diverifikasi oleh mesin backtest yang dapat memenuhi prinsip
Apa artinya mendukung
Selain itu, beberapa pembaca mungkin menemukan bahwa strategi Penny Jump membutuhkan peluang perdagangan pasar, yaitu kebutuhan pasar memiliki setidaknya dua
Dua
Selanjutnya, kita mengamati perbedaan antara
Setelah membersihkan logika trading, kita bisa menggunakan kode untuk mencapainya. karena platform FMZ Quant menggunakan C++ contoh strategi menulis terlalu sedikit, di sini kita menggunakan C++ untuk menulis strategi ini, yang nyaman bagi semua orang untuk belajar, dan ragamnya adalah komoditas berjangka. pertama terbuka:fmz.com> Login > Dashboard > library strategi > New Strategy > Klik menu drop-down di pojok kiri atas > Pilih C ++ untuk mulai menulis strategi, perhatikan komentar dalam kode di bawah ini.
Selanjutnya, mari kita lihat kelas HFT, yang memiliki lima metode. Metode pertama adalah metode konstruksi; metode kedua adalah untuk mendapatkan hari saat ini dari minggu untuk menentukan apakah itu adalah garis K baru; metode ketiga terutama untuk membatalkan semua pesanan yang belum terisi, dan mendapatkan informasi Posisi terperinci, karena sebelum pesanan ditempatkan, harus terlebih dahulu menentukan status posisi saat ini; metode keempat terutama digunakan untuk mencetak beberapa informasi, untuk strategi ini, metode ini bukan yang utama; yang paling penting adalah metode kelima, Metode ini terutama bertanggung jawab untuk memproses logika perdagangan dan menempatkan 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
}
Jadi mari kita lihat bagaimana masing-masing metode dalam kelas HFT ini diimplementasikan, dan bagaimana metode Loop yang paling inti bekerja. Dari atas ke bawah, kita akan mengimplementasikan implementasi spesifik dari setiap metode satu per satu, dan Anda akan menemukan bahwa strategi frekuensi tinggi asli sangat sederhana. Sebelum berbicara tentang kelas HFT, kita pertama kali mendefinisikan beberapa variabel global untuk menyimpan hasil perhitungan objek hft. Mereka adalah: menyimpan status pesanan, status posisi, memegang posisi panjang, memegang posisi pendek, harga beli, jumlah pembelian, harga jual, jumlah penjualan. Silakan lihat kode di bawah ini:
/ / 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 variabel global di atas, kita dapat menyimpan hasil yang dihitung oleh objek hft secara terpisah, yang nyaman untuk panggilan berikutnya oleh program. Selanjutnya kita akan berbicara tentang implementasi spesifik dari setiap metode di kelas HFT. Pertama, metode HFT pertama adalah konstruktor yang memanggil metode getTradingWeekDay kedua dan mencetak hasilnya ke log. Metode getTradingWeekDay kedua mendapatkan hari saat ini dari minggu untuk menentukan apakah itu adalah K baris baru.
Selanjutnya, mari kita mendapatkan semua perintah pertama, mengembalikan hasil adalah array normal, kemudian melintasi array ini, satu per satu untuk membatalkan urutan, kemudian mendapatkan data posisi, mengembalikan array, dan kemudian melintasi Array ini, mendapatkan informasi posisi terperinci, termasuk: arah, posisi, kemarin atau posisi saat ini, dll, dan akhirnya mengembalikan hasilnya; metode berhenti keempat adalah untuk mencetak informasi; kode adalah sebagai 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 fokus pada bagaimana fungsi Loop mengontrol logika strategi dan urutan. Jika Anda ingin melihat lebih hati-hati, Anda dapat merujuk pada komentar dalam kode. Pertama menentukan apakah transaksi CTP dan server pasar terhubung; kemudian mendapatkan saldo akun yang tersedia dan mendapatkan jumlah minggu; kemudian mengatur kode varietas yang akan diperdagangkan, dengan memanggil fungsi resmi FMZ Set QuantContractType, dan dapat menggunakan fungsi ini untuk mengembalikan rincian varietas perdagangan; kemudian memanggil fungsi GetDepth untuk mendapatkan data kedalaman pasar saat ini. Data kedalaman termasuk: harga beli, volume beli, harga jual, volume jual, dll, dan kita menyimpannya dengan variabel, karena akan digunakan nanti; Kemudian output data ini ke bilah status port untuk memudahkan pengguna untuk melihat status pasar saat ini; kode adalah sebagai 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 dapat menempatkan pesanan. Sebelum perdagangan, pertama kita menilai status posisi holding saat ini dari program (tidak ada posisi holding, pesanan posisi panjang, pesanan posisi pendek), di sini kita menggunakan jika...jika...jika kontrol logika. Mereka sangat sederhana, Jika tidak ada posisi holding, posisi akan dibuka sesuai dengan kondisi logika. Jika ada posisi holding, posisi akan ditutup sesuai dengan kondisi logika. Untuk memudahkan semua orang memahami, kita menggunakan tiga paragraf untuk menjelaskan logika, Untuk bagian posisi pembukaan:
Pertama mendeklarasikan variabel Boolean, kita menggunakannya untuk mengontrol posisi penutupan; selanjutnya kita perlu mendapatkan informasi akun saat ini, dan mencatat nilai keuntungan, kemudian menentukan status pesanan penarikan, jika jumlah penarikan melebihi maksimum yang ditetapkan, cetak informasi terkait dalam log; kemudian hitung nilai absolut bid saat ini dan perbedaan harga penawaran untuk menentukan apakah ada lebih dari 2 hop antara harga penawaran saat ini dan harga permintaan.
Selanjutnya, kita mendapatkan harga
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
}
Selanjutnya, kita akan berbicara tentang cara menutup posisi panjang, pertama-tama mengatur jenis order sesuai dengan status posisi saat ini, dan kemudian mendapatkan harga
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 cara menutup posisi pendek. Prinsipnya adalah kebalikan dari posisi panjang penutupan yang disebutkan di atas. Pertama, sesuai dengan status posisi saat ini, atur jenis order, dan kemudian dapatkan harga
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 dari strategi ini.https://www.fmz.com/strategy/163427) untuk menyalin kode sumber strategi lengkap tanpa mengkonfigurasi lingkungan backtest di FMZ Quant.
Untuk memuaskan rasa ingin tahu perdagangan frekuensi tinggi dan untuk melihat hasilnya dengan lebih jelas, biaya transaksi lingkungan backtest strategi ini ditetapkan menjadi 0, yang mengarah ke logika kecepatan cepat yang sederhana. jika Anda ingin menutupi biaya transaksi untuk mencapai profitabilitas di pasar nyata. Lebih banyak optimasi diperlukan. Seperti menggunakan aliran pesanan untuk melakukan prediksi jangka pendek untuk meningkatkan tingkat kemenangan, ditambah pengembalian biaya pertukaran, Untuk mencapai strategi yang menguntungkan yang berkelanjutan, ada banyak buku tentang perdagangan frekuensi tinggi. Saya harap semua orang dapat berpikir lebih banyak dan pergi ke pasar nyata daripada hanya tinggal pada prinsipnya.
FMZ Quant adalah tim yang didorong murni oleh teknologi yang menyediakan mekanisme backtest yang tersedia yang sangat efisien untuk penggemar perdagangan kuantitatif.