替换 FA 分配
replaceFA() 用来替换 TWS 中的 FA 分配配置。它不是“追加一个字段”的接口,而是把传入的完整 XML 写回 TWS。因此它属于高风险修改接口,必须先备份原 XML。
普通账户不应调用 replaceFA()。如果 requestFA() 已经返回 321 non FA customers,说明账户没有 FA 配置可替换。
app.replaceFA(reqId, faData, cxml)| 参数 | 类型 | 中文含义 | 说明 |
|---|---|---|---|
reqId | int | 请求编号 | 用于匹配 replaceFAEnd()。 |
faData | int | FA 数据类型 | 新项目主要替换 1 账户组;旧 Profile 受 TWS 设置影响。 |
cxml | str | 完整 XML 配置 | 会替换对应类型的原配置。 |
replaceFA() 的语义是“整份替换”,不是“局部更新”。如果只想改一个组,也要先读取原 XML、修改目标节点,再把完整 XML 交回 TWS。不要拿文档示例 XML 直接提交。
def replaceFAEnd(self, reqId, text): print("FA 配置替换完成:", reqId, text)收到 replaceFAEnd() 只代表 TWS 处理了替换请求。稳妥做法是替换完成后再次调用 requestFA(),把返回 XML 和预期配置对比。
requestFA() 读取原 XML -> 保存原 XML 备份 -> 用 XML 解析器生成新 XML -> 校验组名、账户数量、方法名 -> replaceFA() 提交完整 XML -> 等待 replaceFAEnd() -> 再次 requestFA() 读取并比对不要手写字符串拼 XML。应该先解析原 XML,再基于节点修改,最后序列化。
import xml.etree.ElementTree as ET
def validate_fa_xml(cxml): root = ET.fromstring(cxml) groups = root.findall(".//Group") if not groups: raise ValueError("XML 中没有找到 Group 节点")
for group in groups: name = group.findtext("name") method = group.findtext("defaultMethod") accounts = group.findall(".//String") if not name: raise ValueError("Group 缺少 name") if not method: raise ValueError(f"Group {name} 缺少 defaultMethod") if not accounts: raise ValueError(f"Group {name} 没有账户")非 FA 账户边界
Section titled “非 FA 账户边界”普通模拟账户请求 requestFA() 可能返回:
ERROR=reqId=-1;code=321;msg=FA data operations ignored for non FA customers.中文界面可能显示为:
ERROR=reqId=-1;code=321;msg=确认请求时出错。:-'X':导致- FA data operations ignored for non FA customers.这种情况下不要尝试 replaceFA()。正确处理是提示用户切换 FA 账户,或把 FA 替换功能隐藏为不可用。