Artikel ini mendemonstrasikan strategi peningkatan volume untuk mempelajari kerangka kerja perdagangan, yang secara fundamental berbeda dari strategi pembentukan pasar arbitrase tradisional. Tujuan utama strategi ini adalah untuk meningkatkan volume perdagangan dengan membeli dan menjual pada harga yang sama, dan mendapatkan rabat pertukaran atau diskon level, alih-alih mendapatkan keuntungan melalui arbitrase selisih harga.
Kode yang disediakan dalam artikel ini hanyalah kerangka kerja referensi dan tidak memiliki pengalaman operasional waktu nyata. Implementasi strategi dalam artikel ini hanya untuk tujuan pembelajaran dan riset teknis dan belum sepenuhnya terverifikasi dalam lingkungan pasar yang sebenarnya. Ketika pembaca merujuk pada konten artikel ini, mereka harus melakukan verifikasi backtesting dan penilaian risiko yang memadai, dan tidak boleh menggunakannya secara langsung untuk trading waktu nyata.
Di pasar mata uang digital, strategi pembuatan pasar (market making) bukan hanya alat untuk meningkatkan likuiditas pasar dan mendorong transaksi, tetapi juga merupakan komponen kunci dari berbagai strategi perdagangan kuantitatif. Para pembuat pasar menghasilkan keuntungan di berbagai lingkungan pasar dengan memasang kuotasi beli dan jual serta menyediakan likuiditas. Implementasi kode pembuat pasar profesional seringkali sangat kompleks, melibatkan fungsi-fungsi lanjutan seperti optimasi penundaan frekuensi tinggi, sistem pengendalian risiko yang kompleks, dan arbitrase multi-bursa. Kali ini, kita akan mempelajari ide dasar strategi counter-trading brush-volume dan cara menerapkan kerangka pembelajaran yang disederhanakan pada platform Inventor Quantitative (FMZ).
Isi utama artikel ini berasal dari “Ide dan Metode Penulisan Strategi Market Making” karya penulis aslinya, Zinan. Beberapa bagian telah dioptimalkan dan direproduksi di platform fmz. Dari perspektif saat ini, beberapa metode penulisan mungkin sudah ketinggalan zaman, tetapi tetap menginspirasi semua orang untuk memahami struktur kode dan ide dasar counter-trading:
Strategi Market Making mengacu pada para pedagang (pembuat pasar) yang menempatkan pesanan beli dan jual di pasar secara bersamaan, sehingga menyediakan likuiditas untuk menjaga stabilitas pasar. Strategi ini tidak hanya membantu menjaga kedalaman pasar, tetapi juga menyediakan rekanan bagi pedagang lain. Dengan menyediakan kuotasi beli dan jual dalam rentang harga yang berbeda, pembuat pasar mendapatkan keuntungan dari fluktuasi harga.
Peran pembuat pasar sangat penting bagi pasar mata uang kripto, terutama di pasar dengan volume perdagangan rendah dan volatilitas tinggi. Dengan menyediakan likuiditas, pembuat pasar membantu mengurangi selip pasar dan menyediakan harga yang lebih mudah bagi para pedagang untuk diperdagangkan.
Prinsip inti dari strategi pembentukan pasar tradisional adalah mendapatkan spread bid-ask dengan menyediakan likuiditas. Harga order beli yang ditetapkan oleh market maker lebih rendah daripada harga order jual, dan keuntungan diperoleh melalui spread transaksi. Misalnya, ketika harga spot di pasar naik, market maker menjual dengan harga lebih tinggi dan membeli dengan harga lebih rendah, sehingga menghasilkan spread. Sumber pendapatan utama meliputi:
Namun, pelaku pasar juga menghadapi risiko volatilitas pasar, terutama dalam lingkungan pasar mata uang digital yang sangat fluktuatif. Fluktuasi tajam di pasar dapat menyebabkan pesanan beli dan jual yang ditempatkan oleh pelaku pasar menyimpang secara signifikan dari harga sebenarnya, yang mengakibatkan kerugian.
Di pasar mata uang kripto, para pelaku pasar biasanya memilih berbagai strategi market making berdasarkan kondisi pasar, volume perdagangan, volatilitas, dan sebagainya. Jenis-jenis strategi market making yang umum meliputi:
Strategi Pembuatan Pasar Pasif:Pembuat pasar menempatkan order beli dan jual berdasarkan kedalaman pasar, volatilitas historis, dan faktor-faktor lainnya, lalu menunggu transaksi pasar. Strategi ini dicirikan oleh frekuensi rendah dan ketahanan, dan pembuat pasar mengandalkan fluktuasi pasar untuk mendapatkan keuntungan.
Strategi pembuatan pasar aktifDengan strategi ini, para pelaku pasar menyesuaikan harga dan jumlah pesanan beli dan jual secara real-time sesuai kondisi pasar untuk meningkatkan kemungkinan terjadinya transaksi. Para pelaku pasar biasanya meningkatkan pesanan ketika harga mendekati harga pasar saat ini untuk memanfaatkan fluktuasi pasar dengan lebih baik.
Strategi peningkatan volume:Jenis strategi yang menjadi fokus artikel ini.Strategi peningkatan volumeIni adalah strategi untuk meningkatkan volume perdagangan dengan membeli dan menjual pada harga yang sama. Berbeda dengan strategi pembentukan pasar tradisional, tujuan utama strategi ini bukanlah untuk mendapatkan selisih harga, melainkan untuk mendapatkan rabat pertukaran, diskon level, atau imbalan penambangan likuiditas melalui sejumlah besar transaksi.
Dalam strategi pencucian volume, pelaku pasar menempatkan order beli dan jual pada harga yang sama. Ketika order dieksekusi, meskipun tidak ada keuntungan selisih harga, volume perdagangan dapat diakumulasikan dengan cepat. Model keuntungan dari strategi ini sepenuhnya bergantung pada mekanisme insentif bursa, alih-alih arbitrase pasar.
Fitur Utama:
Perdagangan harga yang sama:Berbeda dari strategi pembuatan pasar tradisional, harga beli dan harga jual adalah sama, dan tidak ada keuntungan yang dihasilkan dari selisih harga.
Berorientasi pada volume:Tujuan inti dari strategi ini adalah untuk mengakumulasi volume perdagangan dengan cepat alih-alih arbitrase harga.
Ketergantungan pada insentif:Keuntungan sepenuhnya bergantung pada kebijakan potongan harga bursa, diskon tingkat VIP, atau program insentif pembuat pasar.
Perbedaan penting: Dibandingkan dengan strategi pembentukan pasar tradisional, strategi perdagangan cuci (wash trading) tidak menghasilkan keuntungan dengan menyediakan likuiditas pasar yang nyata, melainkan dengan menciptakan volume perdagangan secara artifisial untuk mendapatkan imbalan kebijakan dari bursa. Strategi ini mungkin menghadapi risiko kepatuhan di beberapa yurisdiksi dan perlu dievaluasi secara cermat saat diterapkan dalam praktik.
Dengan menganalisis kode, kita dapat menemukan bahwa harga beli dan harga jual dalam strategi ini persis sama:
def make_duiqiao_dict(self, trade_amount):
mid_price = self.mid_price # 中间价
trade_price = round(mid_price, self.price_precision) # 精准交易价格
trade_dict = {
'trade_price': trade_price, # 买卖都使用同一个价格
'amount': trade_amount
}
return trade_dict
1. Strategi volume perdagangan
2. Mekanisme pengembalian biaya
✅ Skenario yang berlaku
❌ Tidak berlaku
⚠️ Pengingat Risiko
Artikel ini akan merujuk pada kerangka kerja kode Pak Zinan untuk memperkenalkan implementasi sederhana dari strategi peningkatan volume, dengan fokus pada cara mengakumulasi volume perdagangan melalui strategi beli dan jual dengan harga yang sama di lingkungan bursa. Kerangka kerja strategi ini terdiri dari dua kelas utama:MidClass Dan MarketMakerKedua kelas ini bertanggung jawab atas interaksi lapisan tengah pertukaran dan pelaksanaan spesifik strategi lanjutan.
Arsitektur strategi ini mengadopsi desain berlapis, yang memisahkan antarmuka pertukaran dan strategi pembuatan pasar untuk memastikan skalabilitas dan fleksibilitas sistem yang baik. Komponen utama dalam arsitektur ini meliputi:
MidClassLapisan tengah bursa bertanggung jawab untuk berinteraksi dengan antarmuka bursa guna memperoleh data pasar, informasi akun, status pesanan, dll. Lapisan ini merangkum semua interaksi dengan bursa eksternal untuk memastikan logika perdagangan dan antarmuka bursa terpisah.MarketMaker:Kelas strategi pembuatan pasar, bertanggung jawab untuk mengeksekusi strategi knock-to-trade, membuat pending order, memeriksa status order, memperbarui status strategi, dll. Kelas ini berinteraksi dengan lapisan tengah bursa untuk menyediakan operasi pembuatan pasar dan knock-to-trade yang spesifik.MidClassSebagai lapisan tengah pertukaran, tanggung jawab utamanya adalah menangani interaksi dengan pertukaran, merangkum semua panggilan API eksternal, dan menyediakan antarmuka yang ringkas untukMarketMakerPenggunaan. Arsitekturnya mencakup fungsi-fungsi utama berikut:
Akuisisi data pasar:
Manajemen informasi akun:
Manajemen Pesanan:
Penyimpanan dan pembaruan data:
Dengan merangkum fungsi-fungsi ini dalamMidClassDalam contoh di atas, Anda dapat memastikan bahwa kelas strategi perdagangan (sepertiMarketMakerFokus pada eksekusi strategi perdagangan tanpa perlu khawatir tentang cara berinteraksi dengan bursa. Struktur ini meningkatkan kemudahan pemeliharaan dan skalabilitas sistem, sehingga memudahkan penambahan dukungan untuk berbagai bursa atau mengoptimalkan fungsi yang ada.
MarketMakerIni adalah kelas inti dari strategi perdagangan silang, yang bertanggung jawab untuk menjalankan operasi pembentukan pasar dan transaksi perdagangan silang. Arsitekturnya mencakup modul-modul utama berikut:
inisialisasi:
MidClass, dapatkan informasi dasar bursa, seperti pasangan perdagangan, akurasi, kedalaman pasar, dll.Penyegaran data:
Eksekusi strategi ketukan:
MarketMakerIni akan diajukan ke pasar dan order beli serta jual akan dieksekusi secara bersamaan. Tujuannya adalah untuk mengumpulkan volume perdagangan dengan cepat melalui pembelian dan penjualan pada harga yang sama.MarketMakerStatus pesanan akan terus diperiksa untuk memastikan pesanan tertunda dapat diproses tepat waktu. Jika pesanan gagal dieksekusi, harga atau kuantitas pesanan tertunda akan disesuaikan hingga pesanan selesai.Pembaruan Status:
MarketMakerMetode pelaksanaan strategi akan disesuaikan secara dinamis untuk beradaptasi dengan lingkungan pasar yang berbeda.Penerapan strategi perdagangan silang bergantung pada data pasar yang akurat dan eksekusi yang cepat.MarketMakerDengan memantau situasi pasar secara real-time dan memanfaatkan metode counter-order (membeli dan menjual pada harga yang sama), tujuan strategis dapat dicapai dengan mengakumulasi volume perdagangan secara cepat.
ada MarketMakerDalam metode inisialisasi kelas, pertama-tama peroleh informasi akurasi bursa dan inisialisasi parameter strategi, seperti akurasi volume transaksi, akurasi harga, dll.
self.precision_info = self.exchange_mid.get_precision() # 获取精度信息
self.price_precision = self.precision_info['price_precision'] # 价格精度
self.amount_precision = self.precision_info['amount_precision'] # 交易量精度
Inti dari strategi perdagangan silang adalah menghasilkan kamus pesanan perdagangan silang, termasuk harga dan kuantitas beli dan jual. Kode tersebut menghasilkan kamus pesanan perdagangan silang dengan menghitung harga tengah.
def make_duiqiao_dict(self, trade_amount):
mid_price = self.mid_price # 中间价
trade_price = round(mid_price, self.price_precision) # 精准交易价格
trade_dict = {
'trade_price': trade_price,
'amount': trade_amount
}
return trade_dict
Berdasarkan kamus yang dihasilkan dari perintah perdagangan silang, transaksi perdagangan silang dieksekusi.create_orderMetode, tempatkan pesanan beli dan pesanan jual pada saat yang sama.
def make_trade_by_dict(self, trade_dict):
if self.position_amount > trade_dict['amount'] and self.can_buy_amount > trade_dict['amount']:
buy_id = self.exchange_mid.create_order('buy', trade_dict['trade_price'], trade_dict['amount']) # 挂买单
sell_id = self.exchange_mid.create_order('sell', trade_dict['trade_price'], trade_dict['amount']) # 挂卖单
self.traded_pairs['dui_qiao'].append({
'buy_id': buy_id, 'sell_id': sell_id, 'init_time': time.time(), 'amount': trade_dict['amount']
})
Periksa status pesanan secara berkala dan proses pesanan yang belum selesai.GetOrderMetode, dapatkan status pesanan, dan putuskan apakah akan membatalkan pesanan berdasarkan status pesanan tersebut. Logika pemrosesan knock order terutama mencakup langkah-langkah berikut:
Dapatkan status pesanan:
Penilaian status pesanan:
0(ORDER_STATE_PENDING): Belum selesai (pesanan tertunda).1(ORDER_STATE_CLOSED): Selesai (diperdagangkan penuh).2(ORDER_STATE_CANCELED): Dicabut.3(ORDER_STATE_UNKNOWN): Status tidak diketahui.Pemrosesan status pesanan:
0), maka berdasarkan waktu pemungutan suara (current_time % 5 == 0) memutuskan apakah akan membatalkan pesanan.1), dan pesanan lain belum selesai (statusnya0), lalu putuskan apakah akan membatalkan pesanan yang belum selesai berdasarkan waktu pemungutan suara.1), volume transaksi diperbarui dan pesanan dihapus dari catatan.0Tidak terlalu1, statusnya dicatat sebagai tidak diketahui dan dicatat.Perbarui Rekaman:
Strategi peningkatan volume yang disajikan dalam artikel ini terutama digunakan untuk mempelajari desain arsitektur kerangka kerja perdagangan, dan nilai penerapannya sebenarnya terbatas. Jika pembaca tertarik dengan strategi market-making yang sesungguhnya, kami akan memperkenalkan konten strategi yang lebih praktis nanti:
1. Strategi pembuatan pasar
2. Strategi pembuatan pasar yang dinamis
3. Strategi pembuatan pasar bertingkat
Strategi ini akan lebih fokus pada logika keuntungan aktual dan manajemen risiko, sehingga memberikan referensi yang lebih berharga bagi pedagang kuantitatif.
Strategi wash trading bergantung pada kebijakan insentif bursa. Jika kebijakan berubah, strategi tersebut dapat menjadi tidak valid. Oleh karena itu, strategi tersebut harus mampu beradaptasi dengan perubahan kebijakan, seperti memantau tingkat biaya secara dinamis atau memperkenalkan beberapa model keuntungan untuk mengurangi risiko ketergantungan tunggal. Selain itu, strategi wash trading dapat dianggap sebagai manipulasi pasar dan menghadapi risiko regulasi. Dalam penerapannya, pedagang perlu mencermati peraturan dan perundang-undangan yang berlaku untuk memastikan kepatuhan strategi dan menghindari kerugian akibat masalah regulasi.
Saya berharap para pembaca dapat lebih mengoptimalkan dan meningkatkan strategi mereka berdasarkan konsep perdagangan dan pemahaman pasar mereka sendiri, berdasarkan pemahaman mereka tentang kerangka dasar. Pesona perdagangan kuantitatif terletak pada pembelajaran, praktik, dan peningkatan yang berkelanjutan. Saya berharap Anda semua terus maju di jalur perdagangan kuantitatif!
import time, json
class MidClass:
def __init__(self, exchange_instance):
'''
初始化交易所中间层
Args:
exchange_instance: FMZ的交易所结构
'''
self.init_timestamp = time.time() # 记录初始化时间
self.exchange = exchange_instance # 保存交易所对象
self.exchange_name = self.exchange.GetName() # 获取交易所名称
self.trading_pair = self.exchange.GetCurrency() # 获取交易对名称(如 BTC_USDT)
def get_precision(self):
'''
获取交易对的精度信息
Returns:
返回包含精度信息的字典,失败时返回 None
'''
symbol_code = self.exchange.GetCurrency()
ticker = self.exchange.GetTicker(symbol_code) # 回测系统需要
exchange_info = self.exchange.GetMarkets()
data = exchange_info.get(symbol_code)
if not data:
Log("获取市场信息失败", GetLastError())
return None
# 获取该交易对的精度信息
self.precision_info = {
'tick_size': data['TickSize'], # 价格精度
'amount_size': data['AmountSize'], # 数量精度
'price_precision': data['PricePrecision'], # 价格小数位精度
'amount_precision': data['AmountPrecision'], # 数量小数位精度
'min_qty': data['MinQty'], # 最小下单数量
'max_qty': data['MaxQty'] # 最大下单数量
}
return self.precision_info
def get_account(self):
'''
获取账户信息
Returns:
获取信息成功返回 True,获取信息失败返回 False
'''
self.balance = '---' # 账户余额
self.amount = '---' # 账户持仓量
self.frozen_balance = '---' # 冻结余额
self.frozen_stocks = '---' # 冻结持仓量
self.init_balance = None
self.init_stocks = None
self.init_equity = None
try:
account_info = self.exchange.GetAccount() # 获取账户信息
self.balance = account_info['Balance'] # 更新账户余额
self.amount = account_info['Stocks'] # 更新持仓量
self.frozen_balance = account_info['FrozenBalance'] # 更新冻结余额
self.frozen_stocks = account_info['FrozenStocks'] # 更新冻结持仓量
self.equity = self.balance + self.frozen_balance + (self.amount + self.frozen_stocks) * self.last_price
if not self.init_balance or not self.init_stocks or not self.init_equity:
if _G("init_balance") and _G("init_balance") > 0 and _G("init_stocks") and _G("init_stocks") > 0:
self.init_balance = round(_G("init_balance"), 2)
self.init_stocks = round(_G("init_stocks"), 2)
self.init_equity = round(_G("init_equity"), 2)
else:
self.init_balance = round(self.balance + self.frozen_balance, 2)
self.init_stocks = self.amount + self.frozen_stocks
self.init_equity = round(self.init_balance + (self.init_stocks * self.last_price), 2)
_G("init_balance", self.init_balance)
_G("init_stocks", self.init_stocks)
_G("init_equity", self.init_equity)
Log('获取初始eqity', self.init_equity)
self.profit = self.equity - self.init_equity
self.profitratio = round((self.equity - self.init_equity)/self.init_equity, 4) * 100
return True
except:
return False # 获取账户信息失败
def get_ticker(self):
'''
获取市价信息(如买一价、卖一价、最高价、最低价等)
Returns:
获取信息成功返回 True,获取信息失败返回 False
'''
self.high_price = '---' # 最高价
self.low_price = '---' # 最低价
self.sell_price = '---' # 卖一价
self.buy_price = '---' # 买一价
self.last_price = '---' # 最新成交价
self.volume = '---' # 成交量
try:
ticker_info = self.exchange.GetTicker() # 获取市价信息
self.high_price = ticker_info['High'] # 更新最高价
self.low_price = ticker_info['Low'] # 更新最低价
self.sell_price = ticker_info['Sell'] # 更新卖一价
self.buy_price = ticker_info['Buy'] # 更新买一价
self.last_price = ticker_info['Last'] # 更新最新成交价
self.volume = ticker_info['Volume'] # 更新成交量
return True
except:
return False # 获取市价信息失败
def get_depth(self):
'''
获取深度信息(买卖盘的挂单列表)
Returns:
获取信息成功返回 True,获取信息失败返回 False
'''
self.ask_orders = '---' # 卖盘挂单列表
self.bid_orders = '---' # 买盘挂单列表
try:
depth_info = self.exchange.GetDepth() # 获取深度信息
self.ask_orders = depth_info['Asks'] # 更新卖盘挂单列表
self.bid_orders = depth_info['Bids'] # 更新买盘挂单列表
return True
except:
return False # 获取深度信息失败
def get_ohlc_data(self, period=PERIOD_M5):
'''
获取K线信息
Args:
period: K线周期,PERIOD_M1 指1分钟, PERIOD_M5 指5分钟, PERIOD_M15 指15分钟,
PERIOD_M30 指30分钟, PERIOD_H1 指1小时, PERIOD_D1 指一天。
'''
self.ohlc_data = self.exchange.GetRecords(period) # 获取K线数据
def create_order(self, order_type, price, amount):
'''
提交一个挂单信息
Args:
order_type:挂单类型,'buy'指挂买单,'sell'指挂卖单
price:挂单价格
amount:挂单数量
Returns:
挂单Id号,可用以取消挂单
'''
if order_type == 'buy':
try:
order_id = self.exchange.Buy(price, amount) # 提交买单
except:
return False # 买单提交失败
elif order_type == 'sell':
try:
order_id = self.exchange.Sell(price, amount) # 提交卖单
except:
return False # 卖单提交失败
return order_id # 返回订单ID
def get_orders(self):
'''
获取未完成的订单列表
Returns:
未完成的订单列表
'''
self.open_orders = self.exchange.GetOrders() # 获取未完成订单
return self.open_orders
def cancel_order(self, order_id):
'''
取消一个挂单信息
Args:
order_id:希望取消的挂单ID号
Returns:
取消挂单成功返回 True,取消挂单失败返回 False
'''
return self.exchange.CancelOrder(order_id) # 取消订单
def refresh_data(self):
'''
刷新信息(账户、市价、深度、K线)
Returns:
刷新信息成功返回 'refresh_data_finish!' 否则返回相应刷新失败的信息提示
'''
if not self.get_ticker(): # 刷新市价信息
return 'false_get_ticker'
if not self.get_account(): # 刷新账户信息
return 'false_get_account'
if not self.get_depth(): # 刷新深度信息
return 'false_get_depth'
try:
self.get_ohlc_data() # 刷新K线信息
except:
return 'false_get_K_line_info'
return 'refresh_data_finish!' # 刷新成功
class MarketMaker:
def __init__(self, mid_class):
'''
初始化做市策略
Args:
mid_class: 交易所中间层对象
'''
self.exchange_mid = mid_class # 交易所中间层对象
self.precision_info = self.exchange_mid.get_precision() # 获取精度信息
self.done_amount = {'dui_qiao': 0} # 已完成交易量
self.price_precision = self.precision_info['price_precision'] # 价格精度
self.amount_precision = self.precision_info['amount_precision'] # 交易量精度
self.traded_pairs = {'dui_qiao': []} # 已挂单的交易对
self.pending_orders = [] # 未完成的订单状态
self.pending_order_count = 0 # 挂单次数
self.buy_amount = 0
self.sell_amount = 0
self.fee = 0
self.fee_rate = 0.08 / 100
self.chart = {
"__isStock": True,
"tooltip": {"xDateFormat": "%Y-%m-%d %H:%M:%S, %A"},
"title": {"text": "挂单数量"},
"xAxis": {"type": "datetime"},
"yAxis": {
"title": {"text": "挂单数量"},
"opposite": False
},
"series": [
{"name": "挂单买量", "id": "挂单买量", "data": []},
{"name": "挂单卖量", "id": "挂单卖量", "dashStyle": "shortdash", "data": []}
]
}
def refresh_data(self):
'''
刷新数据(账户、市价、深度、K线)
'''
self.exchange_mid.refresh_data() # 刷新交易所数据
self.position_amount = 0 if isinstance(self.exchange_mid.amount, str) else self.exchange_mid.amount # 持仓量
self.available_balance = 0 if isinstance(self.exchange_mid.balance, str) else self.exchange_mid.balance # 账户余额
Log('检查ticker', self.exchange_mid.buy_price)
self.can_buy_amount = self.available_balance / float(self.exchange_mid.buy_price) # 可买的数量
self.mid_price = (self.exchange_mid.sell_price + self.exchange_mid.buy_price) / 2 # 中间价
def make_duiqiao_dict(self, trade_amount):
'''
生成对敲挂单字典
Args:
trade_amount: 每次交易量
Returns:
对敲挂单字典列表
'''
Log('3制作对敲挂单字典')
mid_price = self.mid_price # 中间价
trade_price = round(mid_price, self.price_precision) # 精准交易价格
trade_dict = {
'trade_price': trade_price,
'amount': trade_amount
}
Log('返回盘口挂单字典:', trade_dict)
return trade_dict
def make_trade_by_dict(self, trade_dict):
'''
根据交易字典执行交易
Args:
trade_dict: 交易字典
'''
Log('4按照字典开始交易')
self.refresh_data() # 刷新数据
if trade_dict:
Log('当前账户资金: 币数余额: ', self.position_amount, '资金余额: ', self.can_buy_amount)
Log('检查开仓: 币数限制: ', self.position_amount > trade_dict['amount'], '资金限制: ', self.can_buy_amount > trade_dict['amount'])
if self.position_amount > trade_dict['amount'] and self.can_buy_amount > trade_dict['amount']:
buy_id = self.exchange_mid.create_order('buy', trade_dict['trade_price'], trade_dict['amount']) # 挂买单
sell_id = self.exchange_mid.create_order('sell', trade_dict['trade_price'], trade_dict['amount']) # 挂卖单
self.traded_pairs['dui_qiao'].append({
'buy_id': buy_id, 'sell_id': sell_id, 'init_time': time.time(), 'amount': trade_dict['amount']
})
self.last_time = time.time() # 更新上次交易时间
def handle_pending_orders(self):
'''
处理未完成的订单
'''
pending_orders = self.exchange_mid.get_orders() # 获取未完成订单
if len(pending_orders) > 0:
for order in pending_orders:
self.exchange_mid.cancel_order(order['Id']) # 取消未完成订单
def check_order_status(self, current_time):
'''
检查订单状态
current_time: 轮询检查次数
'''
Log('1开始订单信息检查')
Log(self.traded_pairs['dui_qiao'])
self.buy_pending = 0
self.sell_pending = 0
for traded_pair in self.traded_pairs['dui_qiao'].copy():
Log('检查订单:', traded_pair['buy_id'], traded_pair['sell_id'])
try:
buy_order_status = self.exchange_mid.exchange.GetOrder(traded_pair['buy_id']) # 获取买单状态
sell_order_status = self.exchange_mid.exchange.GetOrder(traded_pair['sell_id']) # 获取卖单状态
except:
Log(traded_pair, '取消')
self.exchange_mid.cancel_order(traded_pair['buy_id']) # 取消买单
self.exchange_mid.cancel_order(traded_pair['sell_id']) # 取消卖单
self.traded_pairs['dui_qiao'].remove(traded_pair) # 移除订单
return
Log('检查订单:', traded_pair['buy_id'], buy_order_status, traded_pair['sell_id'], sell_order_status, [sell_order_status['Status'], buy_order_status['Status']])
if [sell_order_status['Status'], buy_order_status['Status']] == [0, 0]:
self.buy_pending += 1
self.sell_pending += 1
if current_time % 5 == 0:
Log('检查挂单,取消挂单(两未完)', buy_order_status['Status'], sell_order_status['Status'], current_time % 5)
self.exchange_mid.cancel_order(traded_pair['buy_id']) # 取消买单
self.exchange_mid.cancel_order(traded_pair['sell_id']) # 取消卖单
self.pending_order_count += 1 # 挂单次数加1
self.traded_pairs['dui_qiao'].remove(traded_pair) # 移除订单
elif {sell_order_status['Status'], buy_order_status['Status']} == {1, 0}:
if buy_order_status['Status'] == ORDER_STATE_PENDING:
self.buy_pending += 1
if sell_order_status['Status'] == ORDER_STATE_PENDING:
self.sell_pending += 1
if current_time % 5 == 0:
Log('检查挂单,取消挂单(一未完)', buy_order_status['Status'], sell_order_status['Status'])
self.done_amount['dui_qiao'] += traded_pair['amount'] # 更新交易量
if buy_order_status['Status'] == ORDER_STATE_PENDING:
self.sell_amount += traded_pair['amount']
self.fee += sell_order_status['Amount'] * self.fee_rate * sell_order_status['Price']
Log('取消该买订单,增加未完成买列表', traded_pair['buy_id'])
self.exchange_mid.cancel_order(traded_pair['buy_id']) # 取消买单
self.pending_orders.append(['buy', buy_order_status['Status']]) # 记录未完成订单
Log('清除前:', self.traded_pairs['dui_qiao'])
Log('清除id:', traded_pair)
self.traded_pairs['dui_qiao'].remove(traded_pair) # 移除订单
Log('清除后:', self.traded_pairs['dui_qiao'])
elif sell_order_status['Status'] == ORDER_STATE_PENDING:
self.buy_amount += traded_pair['amount']
self.fee += buy_order_status['Amount'] * self.fee_rate * buy_order_status['Price']
Log('取消该卖订单,增加未完成卖列表', traded_pair['sell_id'])
self.exchange_mid.cancel_order(traded_pair['sell_id']) # 取消卖单
self.pending_orders.append(['sell', sell_order_status['Status']]) # 记录未完成订单
Log('清除前:', self.traded_pairs['dui_qiao'])
Log('清除id:', traded_pair)
self.traded_pairs['dui_qiao'].remove(traded_pair) # 移除订单
Log('清除后:', self.traded_pairs['dui_qiao'])
elif [sell_order_status['Status'], buy_order_status['Status']] == [1, 1]:
Log('两订单都已完成')
self.buy_amount += traded_pair['amount']
self.sell_amount += traded_pair['amount']
self.fee += buy_order_status['Amount'] * self.fee_rate * buy_order_status['Price']
self.fee += sell_order_status['Amount'] * self.fee_rate * sell_order_status['Price']
Log('完成状态:', buy_order_status['Status'], sell_order_status['Status'], traded_pair['amount'])
self.done_amount['dui_qiao'] += 2 * traded_pair['amount'] # 更新交易量
self.traded_pairs['dui_qiao'].remove(traded_pair) # 移除订单
else:
Log('两订单处于未知状态:', buy_order_status, sell_order_status)
Log('未知订单状态:', buy_order_status['Status'], sell_order_status['Status'])
Log('未知订单信息:', traded_pair)
def update_status(self):
self.exchange_mid.refresh_data()
table1 = {
"type": "table",
"title": "账户信息",
"cols": [
"初始资金", "现存资金", "对敲买入数量", "对敲卖出数量", "费率", "总收益", "收益率"
],
"rows": [
[
self.exchange_mid.init_equity,
self.exchange_mid.equity,
round(self.buy_amount, 4),
round(self.sell_amount, 4),
round(self.fee, 2),
self.exchange_mid.profit,
str(self.exchange_mid.profitratio) + "%"
],
],
}
LogStatus(
f"初始化时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.exchange_mid.init_timestamp))}\n",
f"`{json.dumps(table1)}`\n",
f"最后执行时间: {_D()}\n"
)
LogProfit(round(self.exchange_mid.profit, 3), '&')
def plot_pending(self):
Log('对敲挂单数量:', self.buy_pending, self.sell_pending)
self.obj_chart = Chart(self.chart)
now_time = int(time.time() * 1000)
# 更新挂单买量数据
self.obj_chart.add(0, [now_time, self.buy_pending])
# 更新挂单卖量数据
self.obj_chart.add(1, [now_time, self.sell_pending])
def main():
'''
主函数,运行做市策略
'''
exchange.IO('simulate', True)
exchange.IO("trade_super_margin")
target_amount = 1 # 目标交易量
trade_amount = 0.01 # 每次交易量
trade_dict = {} # 初始化交易字典
exchange_mid = MidClass(exchange) # 初始化交易所中间层
Log(exchange_mid.refresh_data()) # 刷新数据
market_maker = MarketMaker(exchange_mid) # 初始化做市策略
check_times = 0
while market_maker.done_amount['dui_qiao'] < target_amount: # 循环直到完成目标交易量
Log(market_maker.traded_pairs['dui_qiao'])
market_maker.check_order_status(check_times) # 检查订单状态
Sleep(1000) # 等待1秒
market_maker.refresh_data() # 刷新数据
if len(market_maker.traded_pairs['dui_qiao']) < 1: # 价格移动,盘口挂单撤销,等待至所有挂单完毕,制定新的挂单字典
Log('2盘口交易对数量小于1')
trade_dict = market_maker.make_duiqiao_dict(trade_amount) # 生成盘口挂单字典
Log('新交易字典', trade_dict)
if trade_dict: # 判断字典是否非空
market_maker.make_trade_by_dict(trade_dict) # 执行交易
Log('盘口做市数量:', market_maker.done_amount['dui_qiao']) # 记录交易量
market_maker.plot_pending()
market_maker.update_status()
check_times += 1
Log(market_maker.position_amount, market_maker.can_buy_amount) # 记录持仓量和可买数量
Log('现存订单:', exchange.GetOrders()) # 记录现存订单
def onexit():
Log("执行扫尾函数")
_G("init_balance", None)
_G("init_stocks", None)
_G("init_equity", None)