step tag到quickfix message之间的映射工具

step协议

STEP(Securities trading exchange protocol )证券交易数据交换协议 ,规定了证券交易所交易系统与市场参与者系统之间进行证券交易所需的数据交换协议,规定了应用环境、会话机制、消息格式、安全与加密、数据完整性、扩展方式、消息定义、数据字典等内容。 具体内容参见:证券交易数据交换协议.pdf

quickfix

The Financial Information eXchange (FIX) protocol is a messaging standard developed specifically for the real-time electronic exchange of securities transactions. FIX is a public-domain specification owned and maintained by FIX Protocol, Ltd (FPL).
QuickFIX/J is a full featured messaging engine for the FIX protocol. It is a 100% Java open source implementation of the popular C++ QuickFIX engine.
参见网站https://www.quickfixj.org//

映射工具

需要将如下内容映射到quickfixj对应的message,和将message映射成tag串,如将如下tag串转成message

"8=FIX.5.0\0019=23\00135=D\0011180=010\00111=A0000001\00140=2\00154=1\001522=1\00160=2013022" +
                "8-14:42:13\00148=000001\00122=102\001453=3\001448=000100\0014" +
                "47=C\001452=1\001448=0100004698\001447=5\001452=5\001448=AA\001" +
                "447=D\001452=4001\00138=1200.00\00144=17.4800\001544=1\001";

对应的工具代码如下:

package com.haiyi.tca.exchange.util.step;

import com.google.common.collect.Lists;
import com.haiyi.tca.exchange.model.exception.ExchangeRunTimeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import quickfix.*;
import quickfix.field.BeginString;
import quickfix.field.CheckSum;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * @author: yujiakui
 * @description: STEP tag消息到fix message对应的映射工具
 * @date: 2018/7/14
 * @Time: 上午8:59
 */
@Slf4j
public class StepTag2MsgUtil {

    /**
     * fix消息分割符号
     */
    private static final char FIELD_SEPARATOR = '\001';

    /**
     * 会话数据字典路径
     */
    private static final String SESSSION_DATA_DIC_PATH ;
//    private static final String SESSSION_DATA_DIC_PATH = "D:\\workProject\\i2-tca-exchange\\i2-tca-exchange-biz\\src\\main\\resources\\quickfixj\\FIXT11.xml";

    /**
     * 应用程序数据字典路径
     */
    private static final String APP_DATA_DIC_PATH ;
//    private static final String APP_DATA_DIC_PATH = "D:\\workProject\\i2-tca-exchange\\i2-tca-exchange-biz\\src\\main\\resources\\quickfixj\\quickfixj-app.xml";

    /**
     * 消息工厂类
     */
    public static MessageFactory messageFactory = new DefaultMessageFactory();

    /**
     * 会话数据字典
     */
    public static DataDictionary sessionDataDictionary = null;

    /**
     * 应用数据字典
     */
    public static DataDictionary appDataDictionary = null;


    static {
        try {
            SESSSION_DATA_DIC_PATH =  Class.class.getResource("/quickfixj/FIXT11.xml").getPath();
            APP_DATA_DIC_PATH =  Class.class.getResource("/quickfixj/quickfix-sse.xml").getPath();
            sessionDataDictionary = new DataDictionary(SESSSION_DATA_DIC_PATH);
            appDataDictionary = new DataDictionary(APP_DATA_DIC_PATH);
        } catch (ConfigError configError) {
            log.error("数据字典配置错误{}", configError);
            throw new ExchangeRunTimeException("数据字典配置错误", configError);
        }
    }

    /**
     * tag 字符串转化为Message
     *
     * @param tagStr
     * @return
     */
    public static Message stepTag2Msg(String tagStr) throws InvalidMessage,
            ConfigError, NoSuchMethodException,
            IllegalAccessException, InvocationTargetException {
        String beginString = MessageUtils.getStringField(tagStr
                , BeginString.FIELD);

        String tempTagStr = tagStr;
        if (null == beginString) {
            beginString = FixVersions.FIX50;
            tempTagStr = BeginString.FIELD + "=" +
                    beginString + FIELD_SEPARATOR + tagStr;
        }
        String msgType = MessageUtils.getMessageType(tagStr);

        String checkSumStr = MessageUtils.getStringField(tagStr, CheckSum.FIELD);
        if (null == checkSumStr) {
            String tempCheckTagStr = tempTagStr + CheckSum.FIELD + "=" + 0 + FIELD_SEPARATOR;
            int checkSum = MessageUtils.checksum(tempCheckTagStr);
            tempTagStr = tempTagStr + CheckSum.FIELD + "=" + checkSum + FIELD_SEPARATOR;
        }

        final quickfix.Message message = messageFactory.create(beginString, msgType);
        message.fromString(tempTagStr,sessionDataDictionary,appDataDictionary,appDataDictionary!=null);

        return message;

    }


    /**
     * message 转为tagStr
     *
     * @param message
     * @return
     */
    public static String msg2TagStr(Message message) {

        return msg2TagStr(message, null);
    }

    /**
     * 根据应用字段对消息进行校验
     *
     * @param message
     */
    private static void msgValidateByDataDict(Message message) {
        try {
            appDataDictionary.validate(message, true);
        } catch (IncorrectTagValue incorrectTagValue) {
            log.error("tag值不正确{}", incorrectTagValue);
            throw new ExchangeRunTimeException("tag值不正确", incorrectTagValue);
        } catch (FieldNotFound fieldNotFound) {
            log.error("字段找不到{}", fieldNotFound);
            throw new ExchangeRunTimeException("字段找不到", fieldNotFound);
        } catch (IncorrectDataFormat incorrectDataFormat) {
            log.error("数据格式不正确{}", incorrectDataFormat);
            throw new ExchangeRunTimeException("数据格式不正确", incorrectDataFormat);
        }
    }

    /**
     * message 转为tagStr
     *
     * @param message
     * @param removeTagLists
     * @return
     */
    public static String msg2TagStr(Message message, List<Integer> removeTagLists) {

        // 消息校验
        msgValidateByDataDict(message);
        List<Integer> removeTags = Lists.newArrayList();
        if(removeTagLists!=null){
            removeTags = Lists.newArrayList(removeTagLists);
        }
        if (!message.getHeader().isSetField(BeginString.FIELD)) {
            message.getHeader().setField(new BeginString(FixVersions.FIX50));
            removeTags.add(BeginString.FIELD);
        }
        if (!message.getTrailer().isSetField(CheckSum.FIELD)) {
            message.getTrailer().setField(new CheckSum("0"));
            removeTags.add(CheckSum.FIELD);
        }
        String tagStr = message.toString();

        return removeTagsFromStr(tagStr, removeTags);
    }

    /**
     * 移除tag对应的列表
     *
     * @param sourceTagStr
     * @param removeTags
     * @return
     */
    private static String removeTagsFromStr(String sourceTagStr, List<Integer> removeTags) {
        if (CollectionUtils.isEmpty(removeTags)) {
            return sourceTagStr;
        }
        StringBuilder resultStringBuilder = new StringBuilder(sourceTagStr);
        for (Integer tag : removeTags) {
            int tagIndex = resultStringBuilder.indexOf(tag + "=");
            int tagValueEndIndex = resultStringBuilder.indexOf(String.valueOf(FIELD_SEPARATOR), tagIndex + 2);
            resultStringBuilder.delete(tagIndex, tagValueEndIndex + 1);
        }
        return resultStringBuilder.toString();
    }

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, InvalidMessage, ConfigError {

        String tagStr = "8=FIX.5.0\0019=23\00135=D\0011180=010\00111=A0000001\00140=2\00154=1\001522=1\00160=2013022" +
                "8-14:42:13\00148=000001\00122=102\001453=3\001448=000100\0014" +
                "47=C\001452=1\001448=0100004698\001447=5\001452=5\001448=AA\001" +
                "447=D\001452=4001\00138=1200.00\00144=17.4800\001544=1\001";

        int index = tagStr.indexOf("\001");
        System.out.println("index=" + index);
        String result = String.valueOf(FIELD_SEPARATOR);
        System.out.println(String.valueOf(FIELD_SEPARATOR));
        //String replaceResult = tagStr.replaceAll("\\001", String.valueOf(FIELD_SEPARATOR));

        System.out.println("=======>=====");

        index = tagStr.indexOf(FIELD_SEPARATOR);
        System.out.println("index1=" + index);
        System.out.println(tagStr);
        Message message = stepTag2Msg(tagStr);
        System.out.println(message);

        String tagStrResult = msg2TagStr(message, Lists.<Integer>newArrayList(8, 10));
        System.out.println("-------------------------------");
        System.out.println(tagStrResult);

    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,328评论 19 139
  • 一.函数 1.1 调用函数: Python内置了很多有用的函数,我们可以直接调用。要调用一个函数,需要知道...
    Mr_dvbkhm阅读 4,221评论 0 1
  • 早餐 八宝粥 煎地瓜 伴萝卜 伴海带丝 ,,,一天从早饭开始, 边吃饭,眼睛瞟向窗外。天有些阴,但一缕阳光突然从云...
    小老郑阅读 1,443评论 2 3
  • 又成功一次哄娃睡觉,把自己哄睡着了。 不过现在脑袋还是比较清醒的。 可以毫无打扰的想想如何写晨读感悟。 早上在晨读...
    阿蜜儿阅读 2,405评论 0 3
  • #本文参加‘青春’大赛,本人保证本文为本人原创,如有问题则与主办方无关,自愿放弃评优评奖资格。 姓名:娄一尹 学校...
    鸶一阅读 1,755评论 0 4