Este artigo demonstra uma estratégia de aumento de volume para aprender a estrutura de negociação, que é fundamentalmente diferente da estratégia tradicional de arbitragem de mercado. O principal objetivo dessa estratégia é aumentar o volume de negociação comprando e vendendo ao mesmo preço e obter descontos na bolsa ou em níveis, em vez de obter lucros por meio da arbitragem de diferença de preços.
O código fornecido neste artigo é apenas uma estrutura de referência e não possui nenhuma experiência operacional em tempo real. A implementação da estratégia neste artigo é apenas para fins de aprendizado técnico e pesquisa e não foi totalmente verificada no ambiente de mercado real. Ao consultar o conteúdo deste artigo, os leitores devem realizar verificações de backtesting e avaliações de risco suficientes, e não devem utilizá-lo diretamente para negociações em tempo real.
No mercado de moedas digitais, as estratégias de formação de mercado não são apenas uma ferramenta para melhorar a liquidez do mercado e promover transações, mas também um componente-chave de muitas estratégias de negociação quantitativa. Os formadores de mercado obtêm lucros em diferentes ambientes de mercado, publicando cotações de compra e venda e fornecendo liquidez. A implementação de código de formadores de mercado profissionais costuma ser extremamente complexa, envolvendo funções avançadas como otimização de atraso de alta frequência, sistemas complexos de controle de risco e arbitragem em múltiplas bolsas. Desta vez, estudaremos os conceitos básicos da estratégia de contra-negociação de volume de pincel e como implementar uma estrutura de aprendizado simplificada na plataforma Inventor Quantitative (FMZ).
O corpo principal deste artigo é extraído de “A Ideia e o Método de Escrita da Estratégia de Criação de Mercado”, do autor original Zinan. Algumas partes foram otimizadas e reproduzidas na plataforma fmz. Da perspectiva atual, alguns métodos de escrita podem estar desatualizados, mas ainda assim é inspirador para todos entenderem a estrutura do código e os conceitos básicos do counter-trading:
A Estratégia de Criação de Mercado consiste em traders (formadores de mercado) colocarem ordens de compra e venda no mercado simultaneamente, fornecendo liquidez para manter a estabilidade do mercado. Essa estratégia não apenas ajuda a manter a profundidade do mercado, mas também fornece contrapartes para outros traders. Ao fornecer cotações de compra e venda em diferentes faixas de preço, os formadores de mercado lucram com as flutuações de preço.
O papel dos formadores de mercado é crucial para o mercado de criptomoedas, especialmente em mercados com baixos volumes de negociação e alta volatilidade. Ao fornecer liquidez, os formadores de mercado ajudam a reduzir a derrapagem do mercado e oferecem aos traders preços mais fáceis de negociar.
O princípio fundamental da estratégia tradicional de formação de mercado é obter o spread entre compra e venda, fornecendo liquidez. O preço da ordem de compra publicado pelo formador de mercado é inferior ao preço da ordem de venda, e os lucros são obtidos por meio do spread da transação. Por exemplo, quando o preço à vista no mercado sobe, o formador de mercado vende a um preço mais alto e compra a um preço mais baixo, obtendo o spread. As principais fontes de receita incluem:
No entanto, os formadores de mercado também enfrentam o risco de volatilidade, especialmente no ambiente altamente volátil do mercado de moedas digitais. As flutuações bruscas do mercado podem fazer com que as ordens de compra e venda emitidas pelos formadores de mercado se desviem significativamente do preço real, resultando em perdas.
No mercado de criptomoedas, os formadores de mercado geralmente escolhem diferentes estratégias de criação de mercado com base nas condições de mercado, volume de negociação, volatilidade, etc. Os tipos comuns de estratégias de criação de mercado incluem:
Estratégias de criação de mercado passiva:Os formadores de mercado emitem ordens de compra e venda com base na profundidade do mercado, volatilidade histórica e outros fatores, e aguardam as transações de mercado. Essa estratégia é caracterizada por baixa frequência e robustez, e os formadores de mercado dependem das flutuações do mercado para obter lucros.
Estratégia de criação de mercado ativa: Com essa estratégia, os formadores de mercado ajustam o preço e a quantidade das ordens de compra e venda em tempo real, de acordo com as condições de mercado, para aumentar a probabilidade de um acordo. Os formadores de mercado geralmente aumentam as ordens quando o preço está próximo do preço de mercado atual para aproveitar melhor as flutuações do mercado.
Estratégia de aumento de volume:O tipo de estratégia em que este artigo se concentra.Estratégia de aumento de volumeÉ uma estratégia para aumentar o volume de negociação comprando e vendendo ao mesmo preço. Ao contrário das estratégias tradicionais de criação de mercado, o principal objetivo desta estratégia não é obter diferenças de preço, mas sim obter descontos na bolsa, descontos de nível ou recompensas de mineração de liquidez por meio de um grande número de transações.
Na estratégia de lavagem de volume, os formadores de mercado colocam ordens de compra e venda ao mesmo preço. Quando as ordens são executadas, embora não haja lucro por diferença de preço, o volume de negociação pode ser acumulado rapidamente. O modelo de lucro dessa estratégia depende inteiramente do mecanismo de incentivo da bolsa, e não da arbitragem de mercado.
Principais características:
Negociação pelo mesmo preço:Diferente das estratégias tradicionais de criação de mercado, o preço de compra e o preço de venda são os mesmos, e não há lucro gerado pela diferença de preço.
Orientado para o volume:O objetivo principal da estratégia é acumular rapidamente volume de negociação em vez de arbitragem de preços.
Dependência de incentivos:Os lucros dependem completamente da política de descontos da bolsa, dos descontos de nível VIP ou dos programas de incentivo aos formadores de mercado.
Diferenças importantes: Em comparação com as estratégias tradicionais de formação de mercado, as estratégias de wash trading não geram lucro ao fornecer liquidez real ao mercado, mas sim ao criar artificialmente um volume de negociação para obter recompensas políticas da bolsa. Essa estratégia pode enfrentar riscos de conformidade em algumas jurisdições e precisa ser cuidadosamente avaliada quando aplicada na prática.
Ao analisar o código, podemos descobrir que o preço de compra e o preço de venda nesta estratégia são exatamente os mesmos:
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. Estratégia de volume de negociação
2. Mecanismo de reembolso de taxas
✅ Cenários aplicáveis
❌ Não aplicável
⚠️ Lembrete de Risco
Este artigo se referirá à estrutura de código do Sr. Zinan para apresentar uma implementação simples de uma estratégia de aumento de volume, com foco em como acumular volume de negociação por meio da estratégia de compra e venda com o mesmo preço em um ambiente de bolsa. A estrutura da estratégia consiste em duas classes principais:MidClass e MarketMakerEssas duas classes são responsáveis pela interação da camada intermediária da troca e pela execução específica da estratégia de knock-on.
Esta arquitetura estratégica adota um design em camadas, que separa a interface de negociação e a estratégia de criação de mercado para garantir que o sistema tenha boa escalabilidade e flexibilidade. Os principais componentes da arquitetura incluem:
MidClass:A camada intermediária da bolsa é responsável por interagir com a interface da bolsa para obter dados de mercado, informações da conta, status do pedido, etc. Essa camada encapsula todas as interações com bolsas externas para garantir que a lógica de negociação e a interface da bolsa sejam dissociadas.MarketMaker:Classe de estratégia de criação de mercado, responsável por executar a estratégia knock-to-trade, gerar ordens pendentes, verificar o status da ordem, atualizar o status da estratégia, etc. Ela interage com a camada intermediária da bolsa para fornecer operações específicas de criação de mercado e knock-to-trade.MidClassComo camada intermediária da troca, sua principal responsabilidade é lidar com a interação com a troca, encapsular todas as chamadas de API externas e fornecer uma interface concisa paraMarketMakerUtilização. Sua arquitetura inclui as seguintes funções principais:
Aquisição de dados de mercado:
Gerenciamento de informações de conta:
Gerenciamento de pedidos:
Armazenamento e atualização de dados:
Ao encapsular essas funções emMidClassNo exemplo acima, você pode garantir que a classe de estratégia de negociação (comoMarketMaker) Concentre-se na execução de estratégias de negociação sem se preocupar com a interação com as corretoras. Essa estrutura melhora a manutenibilidade e a escalabilidade do sistema, facilitando a adição de suporte para diferentes corretoras ou a otimização de funções existentes.
MarketMakerÉ a classe central da estratégia de cross-trading, responsável pela execução de operações de formação de mercado e transações de cross-trading. Sua arquitetura inclui os seguintes módulos principais:
inicialização:
MidClass, obtenha informações básicas da bolsa, como pares de negociação, precisão, profundidade de mercado, etc.Atualização de dados:
Execução da estratégia de knock:
MarketMakerEle será enviado ao mercado e as ordens de compra e venda serão executadas simultaneamente. O objetivo é acumular rapidamente volume de negociação comprando e vendendo ao mesmo preço.MarketMakerEle verificará constantemente o status do pedido para garantir que o pedido pendente possa ser processado a tempo. Caso o pedido não seja executado, o preço ou a quantidade do pedido pendente serão ajustados até que ele seja concluído.Atualização de status:
MarketMakerO método de execução da estratégia será ajustado dinamicamente para se adaptar a diferentes ambientes de mercado.A implementação da estratégia de cross-trading depende de dados de mercado precisos e execução rápida.MarketMakerAo monitorar a situação do mercado em tempo real e utilizar o método de contra-ordem (compra e venda pelo mesmo preço), os objetivos estratégicos podem ser alcançados acumulando rapidamente o volume de negociação.
existirMarketMakerNo método de inicialização de classe, primeiro obtenha as informações de precisão da bolsa e inicialize os parâmetros da estratégia, como precisão do volume de transações, precisão do preço, etc.
self.precision_info = self.exchange_mid.get_precision() # 获取精度信息
self.price_precision = self.precision_info['price_precision'] # 价格精度
self.amount_precision = self.precision_info['amount_precision'] # 交易量精度
O núcleo da estratégia de cross-trading é gerar um dicionário de ordens de cross-trading, incluindo os preços de compra e venda e as quantidades. O código gera o dicionário de ordens de cross-trading calculando o preço médio.
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
De acordo com o dicionário gerado de ordens de negociação cruzada, a transação de negociação cruzada é executada.create_orderMétodo, coloque ordens de compra e ordens de venda ao mesmo tempo.
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']
})
Verifique regularmente o status do pedido e processe pedidos não concluídos.GetOrderMétodo: obtenha o status do pedido e decida se deseja cancelá-lo com base no status. A lógica de processamento do pedido de batida inclui principalmente as seguintes etapas:
Obter status do pedido:
Julgamento do status do pedido:
0(ORDER_STATE_PENDING): Não concluído (pedido pendente).1(ORDER_STATE_CLOSED): Concluído (totalmente negociado).2(ORDER_STATE_CANCELED): Revogado.3(ORDER_STATE_UNKNOWN): Status desconhecido.Processamento do status do pedido:
0), então de acordo com os horários das urnas (current_time % 5 == 0) decide se deve cancelar o pedido.1), e outro pedido não for concluído (o status é0) e então decida se deseja cancelar o pedido inacabado com base nos horários de votação.1), o volume da transação é atualizado e o pedido é removido do registro.0Na verdade1, ele é registrado como status desconhecido e registrado.Atualizar registro:
A estratégia de aumento de volume apresentada neste artigo é usada principalmente para aprender o design arquitetônico da estrutura de negociação, e seu valor real de aplicação é limitado. Se os leitores estiverem interessados em estratégias reais de formação de mercado, apresentaremos conteúdo estratégico mais prático posteriormente:
1. Estratégia de criação de mercado
2. Estratégia de criação de mercado dinâmica
3. Estratégia de criação de mercado multinível
Essas estratégias se concentrarão mais na lógica do lucro real e na gestão de risco, fornecendo uma referência mais valiosa para traders quantitativos.
A estratégia de wash trading depende da política de incentivos da bolsa. Se a política mudar, a estratégia pode se tornar inválida. Portanto, a estratégia precisa ser capaz de lidar com mudanças de política, como o monitoramento dinâmico da taxa de comissão ou a introdução de múltiplos modelos de lucro para reduzir o risco de dependência única. Além disso, a estratégia de wash trading pode ser considerada manipulação de mercado e enfrentar riscos regulatórios. Em aplicações reais, os traders precisam estar atentos às leis e regulamentações relevantes para garantir a conformidade da estratégia e evitar perdas devido a questões regulatórias.
Espero que os leitores possam otimizar e aprimorar ainda mais suas estratégias com base em seus próprios conceitos de negociação e conhecimento de mercado, com base em sua compreensão da estrutura básica. O charme do trading quantitativo reside no aprendizado, na prática e no aprimoramento contínuos. Desejo a todos um progresso contínuo no caminho do trading quantitativo!
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)