iOS MiTrader目标整理

2019-07-08  本文已影响0人  Tooyoung_e097
  1. APP 整体结构
  2. APP 初始化流程和后台的交互逻辑
  3. APP 下单盈亏的计算逻辑
  4. APP 里面的计算公式最好结合代码有个总结
  5. APP 开发中的坑的分享和注意事项
  6. iOS socket push消息,和页面接收消息
  7. 异常场景、crash 处理以及日志收集机制
  8. APP K线开发

一、MiTrader整体结构

1、资源目录结构
数据源 MTKlineData 遵循<KLineAbstract>协议
分时图:MinuteChart
蜡烛图:KLineChart
开源的长连接库
https://github.com/acmacalister/jetfire](https://github.com/acmacalister/jetfire)
WebSocket 推送的内容, MTSubscriptionManager 通过 NSHashTable 弱引用方式, 实现了和本地模块的解耦合;
把 OC 的方法注册到桥梁中,让 JS 去调用。
把 JS 的方法注册在桥梁中,让 OC 去调用。
在 mt_bridge.js 中写入js代码 web同事调用 只需要判断 if(window.xxxFunction){}
1.App基础配置Manager
2.相对应MTMemoryCacheManager 存储相关
1.存放用户的信息
2.登录 退出等
3.请求用户基本userData
换肤manager

二、初始化流程和后台的交互逻辑


    if (IS_LOG_IN) {
        [blockArr addObject:^() {
            dispatch_group_enter(group);
            [[MTUserInfoManager sharedManager] fetchUserData:^(BOOL success) {
                dispatch_group_leave(group);
                leaveGroupBlock(success);
            }];
        }];
    } else { //All instrument has been fetched in fetch User data, will run it while non-login
        [blockArr addObject:^() {
            dispatch_group_enter(group);
            [[MTAppConfigManager sharedManager] fetchAllInstrumentInfo:^(BOOL success) {
                dispatch_group_leave(group);
                leaveGroupBlock(success);
            }];
        }];
    }
    
    [blockArr addObject:^() {
        dispatch_group_enter(group);
        [[MTAppConfigManager sharedManager] fetchInstrumentTypes:^(BOOL success) {
            dispatch_group_leave(group);
            leaveGroupBlock(success);
        }];
    }];
    
    [blockArr addObject:^() {
        dispatch_group_enter(group);
        [[MTAppConfigManager sharedManager] fetchInstrumentTranslation:^(BOOL success) {
            dispatch_group_leave(group);
            leaveGroupBlock(success);
        }];
    }];
    
    [blockArr addObject:^() {
        dispatch_group_enter(group);
        [[MTAppConfigManager sharedManager] fetchAllInstrumentStatus:^(BOOL success) {
            dispatch_group_leave(group);
            leaveGroupBlock(success);
        }];
    }];
    [blockArr addObject:^() {
        dispatch_group_enter(group);
        [[MTAppConfigManager sharedManager] fetchWebTracking:^(BOOL success) {
            dispatch_group_leave(group);
            leaveGroupBlock(success);
        }];
       
    }];
dispatch_group_enter(group);
    [MTHttpManager getCustomerDetails:^(MTUserInfoModel *accountDetail) {
        [self saveAccountDetails:accountDetail];
        dispatch_group_leave(group);
        leaveGroupBlock(YES);
    } failureHandler:^(NSError *error) {
        dispatch_group_leave(group);
        leaveGroupBlock(NO);
    }];
    
    // 获取Demo/实盘账户信息
    dispatch_group_enter(group);
    [MTHttpManager getCustomerAccounts:^(NSArray<MTAccountsModel *> *responeseObj) {
        [self saveAccounts:responeseObj];
        dispatch_group_leave(group);
        leaveGroupBlock(YES);
    } failureHandler:^(NSError *error) {
        dispatch_group_leave(group);
        leaveGroupBlock(NO);
    }];
    
    // 获取所有交易工具
    dispatch_group_enter(group);
    [[MTAppConfigManager sharedManager] fetchAllInstrumentInfo:^(BOOL success) {
        dispatch_group_leave(group);
        leaveGroupBlock(success);
    }];
    

    dispatch_group_enter(group);
    [[MTAppConfigManager sharedManager] fetchVerificationStatus:^(BOOL success) {
        dispatch_group_leave(group);
        leaveGroupBlock(success);
    }];

    // 获取自选列表
    dispatch_group_enter(group);
    [[MTAppConfigManager sharedManager] fetchWatchLists:^(BOOL success) {
        dispatch_group_leave(group);
        leaveGroupBlock(success);
    }];
   
    dispatch_group_enter(group); 
    [[MTAppConfigManager sharedManager] fetchAllInstrumentQuatation:^(BOOL success) {
        dispatch_group_leave(group);
        leaveGroupBlock(success);
    }];
    
    dispatch_group_enter(group); 
    [[MTAppConfigManager sharedManager] fetchUserOrders:^(BOOL success) {
        dispatch_group_leave(group);
        leaveGroupBlock(success);
    }];
    
    dispatch_group_enter(group);
    [[MTAppConfigManager sharedManager] fetchNotify:^(BOOL success) {
        dispatch_group_leave(group);
        leaveGroupBlock(success);
    }];
    
    dispatch_group_enter(group);
    [[MTAppConfigManager sharedManager] fetchFundsBalance:^(BOOL success) {
        dispatch_group_leave(group);
        leaveGroupBlock(success);
    }];
    
    
    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (completion) {
                completion(!hasFailure);
            }
            [[MTSubscriptionManager sharedManager] monitorOrderChanges];
            [[MTSubscriptionManager sharedManager] monitorFundsBalanceChanges]; //monitor fund balance when fetch user data. must be is_login
        });
    });

三、开仓以及订单编辑盈亏的计算逻辑

mitrade 的交易业务流程, 包括下单, 修改下单和平仓 3 个部分. 其中下单页面逻辑比较繁琐, 下面详细介绍下它的实现逻辑. 修改下单和平仓页面的逻辑基本和下单页面页面保持一致, 不同的逻辑部分参考注意事项.围计算公式。
1 下单页面

1 初始状态, 止盈\止损\追踪止损\限价保持关闭, 当前价和交易类型保持一致;
2 当打开开关时, 显示最低/最高上限; 价格范围参考公式;
3 修改价格时, 需要盈亏/保证金/价值保持联动;

  1. 计算价值(保留2位小数)

    交易手数x合约量x价格
    
  2. 计算保证金(保留2位小数)

    交易手数x合约量/杠杆x同方向价格(如果是外汇价格为1)
    
  3. 盈亏

    多单盈亏=(平仓价或当前卖价-开仓价)×手数×合约单位
    空单盈亏=(开仓价-平仓价或当前买价)×手数×合约单位
    .
    目前APP使用的是
    盈亏=价格差(在OrderDetailsInfo计算)x手数x合约单位
    .
    交易品种计算
    本币盈亏=CurrencyConverter.converter)当前币种,用户结算币种,盈亏)
    .
    净盈亏 = 本币盈亏+隔夜费(隔夜费是当前用户币种,油服务器计算我们不区分正负)
    
    
  4. 移动止损

    点位 = BigDecimal pip = BigDecimal.ONE
                    .divide(
                        new BigDecimal(Math.pow(10, instrumentInfo.pipPosition))
                    );
    移动止损 = 移动止损数量x点位x手数x合约单位
    
  5. 限价开仓最低止盈止损价范围

    计算对手价(做多对手价 = 卖价/做空对手价=买价)
        限价(挂单)计算价格差
            挂单需要计算价格差,然后计算对手价
            价格差 = 买价-买价
        限价(挂单)
            做多
                买价 = 当前挂单价
                卖价 = 买价-价格差
            做空
                卖价 = 当前挂单价
                买价 = 卖价+价格差
        现价(现价开仓)
            买价 = 买价
            卖价  = 卖价
            
    止盈止损距离 (后台提供)
        defaultTakeProfitOrStopLossPips
    止盈止损最大最小交易范围(后台提供)
        maxPriceMarginRate
    做多止盈
        最低止盈价 = 对手价+止盈止损距离
        最高止盈价 = 对手价+对手价x止盈止损最大最小交易范围
    做空止盈
        最低止盈价 = 对手价x止盈止损最大最小交易范围
        最高止盈价 = 对手价-止盈止损距离
    .
    做多止损
        最低止损 = 对手价x止盈止损最大最小交易范围
        最高止损 = 对手价-止盈止损距离
    做空止损
        最低止损 = 对手价+止盈止损距离
        最高止损 = 对手价+对手价x止盈止损最大最小交易范围
    
  6. 设置挂单价格范围

    挂单距离
        orderSpread
    最大挂单范围(止盈止损最大最小交易范围 同一字段 服务器提供)
        maxPriceMarginRate
    挂单范围分为两类
        BuyLimit(猜顶,摸底)
            做多:摸底 如果以后价<=订单价更低
                最低范围=行情买价x最大挂单范围
                最高范围=行情买价-挂单距离
                
            做空:猜顶 如果以后价>=订单价更高
                最低范围=行情卖价+挂单距离
                最高范围=行情卖价+行情卖价x最大挂单范围距离
        StopLimit
            做多:如果以后价格>=设置的订单价
                最低范围=行情买价+挂单距离
                最高范围=行情买价+行情买价x最大挂单范围距离
            做空:如果以后价格<=设置的订单价
                最低范围=行情卖价x最大挂单范围
                最高范围=行情卖价-挂单距离
    
  7. 交易注意点

1. 对交易相关页面的优化采用集成的方式, 修改下单和平仓继承下单页面,公共方法统一集中在下单页面;
2 修改下单和平仓页面关于 UI 显示和部分价格, 重写了 get 方法;
3 计算不同货币转换时, 统一放在 MTOrder 模型中进行处理;

四、开发中的坑的分享和注意事项

坑1: WebSocket 切换网络问题, 需要在真机中测试, 不要在模拟器;
坑2: 键盘类型在更换时, 通过 resignFirstResponser 取消焦点, 否者会崩溃;
坑3: 项目存在大量对NSMutableDictionary ,NSMutableArray操作,注意操作;
更多小坑, 参考工程 README.md;

五、iOS-Websocket推送消息

  1. iOS中的WebSocket采取STOMP协议 具体可以看这篇文章 https://www.cnblogs.com/my_life/articles/7002138.html
1. JFRWebSocket  底层Webscoket封装 
2. WebsocketStompKit 对JFRWebSocket 进一步封装 实现连接,订阅,取消订阅,心跳等功能,开发人员可以在这里二次订制
3. MTWebsocketManager Mitrade项目业务相关封装
4. MTSubscriptionManager 具体与Controller交互manager

六、异常场景、crash 处理以及日志收集机制

1. Bugly统计crash
2. firebase统计,陈国佳管理
3. 增加AvoidCrash机制处理

七、K线

1.数据源: K数据源遵循<KLineAbstract>协议,分时图数据源遵循<MinuteAbstract>协议,调用对应的初始化,传入数据源。
2. K线 分时图数据更新分别在 KLineChart+Update.h MinuteChart+Update.h 俩个Category中,数据源要遵循相应的协议
3. IndexPeriodManager 处理相对应的K线的指标参数,颜色等。
4. KLineIndexManager  处理指标计算
5. 注意 MTTimeData model处理分时数据。eg 欧元/美元  和 澳洲200指数,开收盘时间不同,需要特殊注意。
上一篇下一篇

猜你喜欢

热点阅读