You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django集成QuickFix执行多函数异常:文件无法访问

问题描述

运行下述集成QuickFix的Django代码时,程序仅执行命令并尝试打开传入文件,无法实现其他功能,同时提示文件不存在或无法打开。

import time
import quickfix
import quickfix44
from django.shortcuts import render
from django.shortcuts import render
import threading
from django.http import JsonResponse
from quickfix import Message, MsgType
from django.views.decorators.csrf import csrf_exempt

symbol=['EURUSD', 'NZDAUD']
messages=[]
messages1=[]
messages2=[]
should_stop_data_flow = True

def messageToString(message):
    ............
def securityListRequest(sessionID):
    ...............

def marketDataRequest(sessionID):
    ............

class Application(quickfix.Application):
    def __init__(self):
        super().__init__()
     
    def onCreate(self, sessionID):
        print("onCreate:")
        self.session_id = sessionID
        target = sessionID.getTargetCompID().getString()
        sender = sessionID.getSenderCompID().getString()
        return
    
    def onLogon(self, sessionID):
        self.sessionID = sessionID
        print("onLogon:", f"Session ID: {self.sessionID}")
        message = marketDataRequest(sessionID)
        print("market data request:", messageToString(message))
        quickfix.Session.sendToTarget(message, sessionID)
  
    def onLogout(self, sessionID):
        print("onLogout..")
        return
    
    def toAdmin(self, message, sessionID):
        print("toAdmin:", messageToString(message), '\n')
        return
    
    def toApp(self, message, sessionID):
        print("toApp:", messageToString(message), '\n')
        return
    
    def fromAdmin(self, message, sessionID):  
        print("fromAdmin:", messageToString(message), '\n')
        return
 
    def fromApp(self, message, sessionID):
        msg = messageToString(message)
        print("fromApp:", msg, '\n')
    
    def keepAlive(self):
        while True:
            time.sleep(30)

def run_fix():
    global app
    settings = quickfix.SessionSettings("CCFIX.ini")
    app = Application()
    storeFactory = quickfix.FileStoreFactory(settings)
    logFactory = quickfix.FileLogFactory(settings)
    initiator = quickfix.SocketInitiator(app, storeFactory, settings, logFactory)
    initiator.start()
    app.keepAlive()

def start_fix_thread():
    fix_thread = threading.Thread(target=run_fix)
    fix_thread.start()

def fix_example_view(request):
    global symbol
    start_fix_thread()       
    return render(request, 'show_messages.html', {'messages': messages})
问题排查与修复方案

1. 配置文件路径问题

提示文件不存在,优先检查以下两点:

  • 确保CCFIX.ini文件放在Django项目根目录(与manage.py同目录),或者使用绝对路径指定文件位置,示例:
    settings = quickfix.SessionSettings("/opt/django_project/CCFIX.ini")
    
  • 确认文件权限,保证Django进程拥有读取该文件的权限。

2. 代码缩进错误

原代码中onLogout、toAdmin等方法未缩进在Application类内部,导致这些方法被识别为全局函数,QuickFix框架无法触发回调。修正后的缩进如上面代码示例所示。

3. 空实现函数补全

messageToString、marketDataRequest等函数仅保留占位符,必须补全实现才能正常工作:

  • 示例messageToString实现:
    def messageToString(message):
        msg_components = []
        # 提取消息头
        header = quickfix.FieldMap()
        message.getHeader().copyTo(header)
        msg_components.append(f"Header: {header}")
        # 提取消息体
        body = quickfix.FieldMap()
        message.copyTo(body)
        msg_components.append(f"Body: {body}")
        # 提取消息尾
        trailer = quickfix.FieldMap()
        message.getTrailer().copyTo(trailer)
        msg_components.append(f"Trailer: {trailer}")
        return "\n".join(msg_components)
    
  • 示例marketDataRequest实现(符合QuickFix4.4规范):
    def marketDataRequest(sessionID):
        msg = quickfix44.MarketDataRequest()
        # 设置请求ID
        msg.setField(quickfix.MDReqID("MD-REQ-001"))
        # 设置订阅类型:快照+更新
        msg.setField(quickfix.SubscriptionRequestType(quickfix.SubscriptionRequestType_SNAPSHOT_PLUS_UPDATES))
        # 设置市场深度
        msg.setField(quickfix.MarketDepth(0))
        
        # 添加行情条目类型(买价+卖价)
        entry_group = quickfix44.MarketDataRequest.NoMDEntryTypes()
        entry_group.setField(quickfix.MDEntryType(quickfix.MDEntryType_BID))
        msg.addGroup(entry_group)
        entry_group.setField(quickfix.MDEntryType(quickfix.MDEntryType_OFFER))
        msg.addGroup(entry_group)
        
        # 添加目标交易对
        symbol_group = quickfix44.MarketDataRequest.NoRelatedSym()
        symbol_group.setField(quickfix.Symbol("EURUSD"))
        msg.addGroup(symbol_group)
        symbol_group.setField(quickfix.Symbol("NZDAUD"))
        msg.addGroup(symbol_group)
        
        return msg
    

4. 消息存储与线程优化

  • fromApp方法未将收到的消息存入messages列表,无法在页面展示,补充代码:
    def fromApp(self, message, sessionID):
        msg = messageToString(message)
        print("fromApp:", msg, '\n')
        global messages
        messages.append(msg)
    
  • keepAlive死循环会阻塞线程,添加退出条件并可选发送心跳包:
    def keepAlive(self):
        global should_stop_data_flow
        while not should_stop_data_flow:
            time.sleep(30)
            # 检查会话是否存活,发送心跳包
            if quickfix.Session.lookupSession(self.sessionID):
                quickfix.Session.sendToTarget(quickfix.Message(), self.sessionID)
    

5. 避免重复启动线程

每次访问视图都会启动新的QuickFix线程,导致多会话冲突,添加启动判断:

fix_thread_running = False

def start_fix_thread():
    global fix_thread_running
    if not fix_thread_running:
        fix_thread = threading.Thread(target=run_fix)
        fix_thread.daemon = True  # 设置为守护线程,随Django进程退出
        fix_thread.start()
        fix_thread_running = True

内容的提问来源于stack exchange,提问作者mery

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 07:15:05