1. 이전 포스팅 확인하기

 

https://growingsaja.tistory.com/942

 

 

 

 

 

2. 이번 목표

 

  a. 2개 거래소로부터 Futures 정보 수집해서 저장 기능 구현

      Bybit, Bitget

 

  b. 주의할 점

      Futures의 경우 Spot에 비해 거래소별로 제공하는 api return data의 형태가 다를 수 있습니다. return data type들을 유사하나 사용방법이나 symbol 표현 방식이 달라 예외처리가 필요합니다.

 

 

 

 

 

3. Default.json의 Bitget api 관련 정보 수정

 

// vim Default.json



// ...




                }
            }
        },
        "Bitget": {
            "isActive": {
                "spot": true,
                "futures": true
            },
            "information": {
                "image": "exchangeBitget.png",
                "keyList": [],
                "baseUrlList": [
                    "https://api.bitget.com"
                ],
                "publicApi": {
                    "ticker": "/api/spot/v1/market/tickers",
                    "orderbook": "",
                    "ticker_futures": "/api/mix/v1/market/tickers",
                    "orderbook_futures": ""
                }
            },
            "spot": {
                "stable": {
                    "category": "spot",
                    "paymentCurrencyList": ["USDT", "USDC"]
                },
                "bitcoin": {
                    "category": "spot",
                    "paymentCurrencyList": ["BTC"]
                },
                "alt": {
                    "category": "spot",
                    "paymentCurrencyList": ["ETH"]
                },
                "fiat": {
                    "category": "spot",
                    "paymentCurrencyList": ["EUR", "RUB", "UAH", "BRL", "GBP"]
                }
            },
            "futures": {
                "stableMargin" : {
                    "category": "usd(s)-m",
                    "paymentCurrencyList": ["USDT", "USDC"],
                    "description": "umcbl = USDT perpetual contract, cmcbl = USDC perpetual contract"
                },
                "coinMargin": {
                    "category": "coin-m",
                    "paymentCurrencyList": ["USD"],
                    "description": "dmcbl = Universal margin perpetual contract"
                }
            }
        },
        "Okx": {
            "isActive": {




// ...

 

 

 

 

 

 

 

4. Bitget 현물 정보 수집 기능 확인

 

// vim SpotBitget.h

@interface SpotBitget : NSObject

// asset, payment currency 기준으로 현재 실시간 정보 얻기
@property (readwrite, strong, nonatomic) NSMutableDictionary *dataFromAsset;
// payment currency 정보
@property (readwrite, strong, nonatomic) NSMutableDictionary *paymentCurrencyInfo;

+(instancetype)sharedInstance;
-(void) fetchDataWithCompletion;

@end

 

// vim SpotBitget.m

#import <Foundation/Foundation.h>
#import "SpotBitget.h"
// 주요 데이터 get
#import "DefaultLoader.h"
// api 연결
#import "APIManager.h"

@implementation SpotBitget

+(instancetype)sharedInstance {
    static SpotBitget *sharedInstance = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        sharedInstance = [[self alloc] init];
        // 가격 정보 초기 설정
        sharedInstance.dataFromAsset = [@{} mutableCopy];
        // 취급 화폐 초기 설정
        sharedInstance.paymentCurrencyInfo = [@{} mutableCopy];
        // payment currency 데이터 참조해서 symbol 찢기 용도 데이터셋 선언
        [sharedInstance getOnlyPaymentCurrencyInfo];
    });
    return sharedInstance;
}

-(void) fetchDataWithCompletion {
    // **************************************** [Start] api 콜 준비 **************************************** //
    NSDictionary *bitget = [DefaultLoader sharedInstance].exchangeInfo[@"Bitget"];
    APIManager* tryApiCall = [APIManager sharedInstance];
    // **************************************** [Start] Bybit 현재 호가, 변동률 등 주요 데이터 가져오기 **************************************** //
    NSString *apiURL = [bitget[@"information"][@"baseUrlList"][0] stringByAppendingString:bitget[@"information"][@"publicApi"][@"ticker"]];
    [tryApiCall fetchDataFromAPI:apiURL withCompletionHandler:^(NSDictionary *jsonResponse, NSError *error) {
        if (error) {
            NSLog(@"[Error] Bitget Spot Api : %@", error.localizedDescription);
        } else {
            // 여기에서 jsonResponse를 가공 한 후 앱에서 사용하실 수 있습니다.
            if ([jsonResponse[@"code"] isEqual:@"00000"]) {
                // ****** 정상 성공시 ****** //
                // 기본적으로 code, msg, requestTime이라는 키값을 가지며, main으로는 data라는 키값을 가지는데, 그 안에 list로 상품별 정보를 가집니다. (requestTime은 unix timestamp입니다.)
                // result 안의 value만 추출
                NSArray* resultOfApi = jsonResponse[@"data"];
                // api로 받은 데이터 깔끔한 dictionary로 가공하기
                for (int i=0; i<resultOfApi.count; i++) {
                    /* #################### dataFromSymbol #################### */
                    // ****** api의 데이터들 수집한거 필요시 가공해서 저장하기 ****** //
                    NSString *symbol = resultOfApi[i][@"symbol"]; // 심볼
                    NSString *price = resultOfApi[i][@"close"]; // 가격
                    // 변동률은 데이터를 다른 거래소 정보와 함께 노출시 통일성있게 하기 위해 부분 가공이 진행됩니다.
                    NSString *changePricePercent24 = [NSString stringWithFormat:@"%.2f", [resultOfApi[i][@"change"] floatValue] * 100]; // 근24시간 가격 변동률
                    if (![changePricePercent24 hasPrefix:@"-"]) {
                        // 음수가 아닌 경우, +로 기호 맨앞에 붙여주기
                        changePricePercent24 = [@"+" stringByAppendingString:changePricePercent24];
                    }
                    NSString *volume24 = resultOfApi[i][@"baseVol"]; // 근24시간 거래량
                    NSString *turnover24 = resultOfApi[i][@"usdtVol"]; // 근24시간 거래대금
                    /* #################### dataFromAsset #################### */
                    // dataFromAsset
                    NSString *asset;
                    NSString *paymentCurrency;
                    // 사용된 payment currency 찾고 symbol을 찢기
                    for (NSString *eachPaymentCurrency in self.paymentCurrencyInfo[@"spot"]) {
                        // 뒤에 payment currency 매치되는거 찾은 경우 분리 진행
                        if ([symbol hasSuffix:eachPaymentCurrency]) {
                            asset = [[symbol componentsSeparatedByString:eachPaymentCurrency] objectAtIndex:0];
                            paymentCurrency = eachPaymentCurrency;
                        }
                    }
                    // ****** 데이터 저장 진행 ****** //
                    if (asset && paymentCurrency) {
                        // symbol을 asset과 payment 분리에 성공한 경우, 정상적인 데이터 수집 절차가 진행됩니다.
                        if ( ! [self.dataFromAsset objectForKey:asset]) {
                            // asset 키값이 없는 경우, 만들어줍니다.
                            self.dataFromAsset[asset] = [@{} mutableCopy];
                        }
                        // dataFromAsset 데이터셋 생성
                        self.dataFromAsset[asset][paymentCurrency] = [@{} mutableCopy];
                        self.dataFromAsset[asset][paymentCurrency][@"price"] = price; // 가격
                        self.dataFromAsset[asset][paymentCurrency][@"changePricePercent24"] = changePricePercent24; // 근24시간 가격 변동률
                        self.dataFromAsset[asset][paymentCurrency][@"turnover24"] = turnover24; // 근24시간 거래대금
                        self.dataFromAsset[asset][paymentCurrency][@"volume24"] = volume24; // 근24시간 거래량
                    } else {
                        // 취급하지 않는 payment currency가 발견된 경우 = default.json에서 개발자가 인지하지 못한 payment currency가 발견된 경우 알림
                        NSLog(@"[WARN] Bitget Spot list doesn't have this payment currency. : %@", symbol);
                    }
                }
            } else {
                // ****** 비정상으로 실패시 ****** //
                // 에러가 발생한 경우 retCode는 0이 아니며, retMsg에 관련 상세 내용이 있습니다.
                NSLog(@"[ERROR] Bitget Spot Return Code : %@, Message : %@", jsonResponse[@"code"], jsonResponse[@"msg"]);
                // api로 받은 데이터 깔끔한 dictionary로 가공하기
            }
        }
    }];
}


// _paymentCurrencyInfo : spot, futures 각각에서 취급하는 paymentCurrencyList를 보유하게 됩니다. 해당 정보를 토대로, symbol 데이터를 활용해 asset과 paymentCurrency를 분리할 수 있습니다.
-(void) getOnlyPaymentCurrencyInfo {
    // bybit 관련 default 데이터 불러오기
    NSDictionary *bitget = [DefaultLoader sharedInstance].exchangeInfo[@"Bitget"];
    NSArray *categoryList = @[@"spot", @"futures"];
    // 데이터 정리하기
    for (NSString *category in categoryList) {
        _paymentCurrencyInfo[category] = [@[] mutableCopy];
        for (NSString *group in [bitget[category] allKeys]) {
            if ([bitget[category][group][@"category"] isEqual:category]) {
                // spot
                [_paymentCurrencyInfo[category] addObjectsFromArray:bitget[category][group][@"paymentCurrencyList"]];
            } else if ([bitget[category][group][@"category"] isEqual:@"coin-m"]) {
                // usd
                [_paymentCurrencyInfo[category] addObjectsFromArray:bitget[category][@"coinMargin"][@"paymentCurrencyList"]];
            } else if ([bitget[category][group][@"category"] isEqual:@"usd(s)-m"]) {
                // usdt
                [_paymentCurrencyInfo[category] addObjectsFromArray:bitget[category][@"stableMargin"][@"paymentCurrencyList"]];
            } else {
                NSLog(@"[WARN] Bitget Spot payment currency not match : Skip... -> bitget[category][group][@\"category\"] : %@", bitget[category][group][@"category"]);
            }
        }
    }
}

@end

 

 

 

 

 

5. Bitget 선물 정보 수집 기능 구현

 

// vim FuturesBitget.h

@interface FuturesBitget : NSObject

// asset, payment currency 기준으로 현재 실시간 정보 얻기
@property (readwrite, strong, nonatomic) NSMutableDictionary *dataFromAsset;

// payment currency 정보
@property (readwrite, strong, nonatomic) NSMutableDictionary *paymentCurrencyInfo;

+(instancetype)sharedInstance;
-(void) fetchDataWithCompletion;

@end

 

// vim FuturesBitget.m

#import <Foundation/Foundation.h>
#import "FuturesBitget.h"
// 주요 데이터 get
#import "DefaultLoader.h"
// api 연결
#import "APIManager.h"

@implementation FuturesBitget

+(instancetype)sharedInstance {
    static FuturesBitget *sharedInstance = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        sharedInstance = [[self alloc] init];
        // 가격 정보 초기 설정
        sharedInstance.dataFromAsset = [@{} mutableCopy];
        // 취급 화폐 초기 설정
        sharedInstance.paymentCurrencyInfo = [@{} mutableCopy];
        // payment currency 데이터 참조해서 symbol 찢기 용도 데이터셋 선언
        [sharedInstance getOnlyPaymentCurrencyInfo];
    });
    return sharedInstance;
}

-(void) fetchDataWithCompletion {
    // **************************************** [Start] api 콜 준비 **************************************** //
    NSDictionary *bitget = [DefaultLoader sharedInstance].exchangeInfo[@"Bitget"];
    APIManager* tryApiCall = [APIManager sharedInstance];
    // **************************************** [Start] Bybit 현재 호가, 변동률 등 주요 데이터 가져오기 **************************************** //
    for (NSString *productType in @[@"umcbl", @"cmcbl", @"dmcbl"]) {
        NSString *apiURL = [bitget[@"information"][@"baseUrlList"][0] stringByAppendingString:bitget[@"information"][@"publicApi"][@"ticker_futures"]];
        apiURL = [apiURL stringByAppendingString:@"?productType="];
        apiURL = [apiURL stringByAppendingString:productType];
        // 각각 USDT, USDC, USD perpetual contract 3개 콜하기
        [tryApiCall fetchDataFromAPI:apiURL withCompletionHandler:^(NSDictionary *jsonResponse, NSError *error) {
            if (error) {
                NSLog(@"[Error] Bitget Futures Api : %@", error.localizedDescription);
            } else {
                // 여기에서 jsonResponse를 가공 한 후 앱에서 사용하실 수 있습니다.
                if ([jsonResponse[@"code"] isEqual:@"00000"]) {
                    // ****** 정상 성공시 ****** //
                    // 기본적으로 code, msg, requestTime이라는 키값을 가지며, main으로는 data라는 키값을 가지는데, 그 안에 list로 상품별 정보를 가집니다. (requestTime은 unix timestamp입니다.)
                    // result 안의 value만 추출
                    NSArray* resultOfApi = jsonResponse[@"data"];
                    // api로 받은 데이터 깔끔한 dictionary로 가공하기
                    for (int i=0; i<resultOfApi.count; i++) {
                        /* #################### dataFromSymbol #################### */
                        // ****** api의 데이터들 수집한거 필요시 가공해서 저장하기 ****** //
                        NSString *symbol = resultOfApi[i][@"symbol"]; // 심볼
                        NSString *price = resultOfApi[i][@"last"]; // 가격
                        // 변동률은 데이터를 다른 거래소 정보와 함께 노출시 통일성있게 하기 위해 부분 가공이 진행됩니다.
                        NSString *changePricePercent24 = [NSString stringWithFormat:@"%.2f", [resultOfApi[i][@"priceChangePercent"] floatValue] * 100]; // 근24시간 가격 변동률
                        if (![changePricePercent24 hasPrefix:@"-"]) {
                            // 음수가 아닌 경우, +로 기호 맨앞에 붙여주기
                            changePricePercent24 = [@"+" stringByAppendingString:changePricePercent24];
                        }
                        NSString *volume24 = resultOfApi[i][@"baseVolume"]; // 근24시간 거래량
                        NSString *turnover24 = resultOfApi[i][@"usdtVolume"]; // 근24시간 거래대금
                        /* #################### dataFromAsset #################### */
                        // dataFromAsset
                        NSString *asset;
                        NSString *paymentCurrency;
                        // Bitget의 symbol은 좀 독특한 형태라 symbol 가공 작업 진행
                        if ([symbol containsString:@"_"]) {
                            // _를 포함한 값으로 symbol이 구성된 경우 (Bitget의 경우 모든 Futures 데이터가 이에 해당한다.)
                            NSArray *symbolArray = [symbol componentsSeparatedByString:@"_"];
                            if (symbolArray.count == 2) {
                                // 해당 경우의 데이터만 취급합니다.
                                symbol = [symbolArray objectAtIndex:0];
                            } else if (symbolArray.count == 3) {
                                // 3개인 경우는 유기한 선물이며 유기한 선물은 취급하지 않습니다.
                                // pass
                            } else if (symbolArray.count < 2) {
                                // 1개 이하인 경우, futures 정보가 아닌 것으로 추측되어 api return 데이터 점검 필요!
                                NSLog(@"[WARN] Bitget Futures symbolArray Count 1 or 0. productType : %@, symbol : %@", productType, symbol);
                            } else {
                                // 4개 이상인 경우, 새로운 형태의 futures가 생긴 것으로 추측되어 api return 데이터 점검 필요
                                NSLog(@"[WARN] Bitget Futures NEW TYPE Exist! productType : %@, symbol : %@", productType, symbol);
                            }
                        }
                        // symbol PERP = USDC 변경 처리
                        if ([symbol hasSuffix:@"PERP"]) {
                            // 뒤에 PERP 매치되는거 찾은 경우 분리 진행 = USDC임
                            asset = [[symbol componentsSeparatedByString:@"PERP"] objectAtIndex:0];
                            paymentCurrency = @"USDC";
                        } else {
                            // 사용된 payment currency 찾고 symbol을 찢기
                            for (NSString *eachPaymentCurrency in self.paymentCurrencyInfo[@"futures"]) {
                                if ([symbol hasSuffix:eachPaymentCurrency]) {
                                    // 뒤에 payment currency 매치되는거 찾은 경우 분리 진행
                                    // 뒤에 payment currency 매치되는거 찾은 경우 분리 진행
                                    asset = [[symbol componentsSeparatedByString:eachPaymentCurrency] objectAtIndex:0];
                                    paymentCurrency = eachPaymentCurrency;
                                }
                            }
                        }
                        // ****** 데이터 저장 진행 ****** //
                        if (asset && paymentCurrency) {
                            // symbol을 asset과 payment 분리에 성공한 경우, 정상적인 데이터 수집 절차가 진행됩니다.
                            if ( ! [self.dataFromAsset objectForKey:asset]) {
                                // asset 키값이 없는 경우, 만들어줍니다.
                                self.dataFromAsset[asset] = [@{} mutableCopy];
                            }
                            // dataFromAsset 데이터셋 생성
                            self.dataFromAsset[asset][paymentCurrency] = [@{} mutableCopy];
                            self.dataFromAsset[asset][paymentCurrency][@"price"] = price; // 가격
                            self.dataFromAsset[asset][paymentCurrency][@"changePricePercent24"] = changePricePercent24; // 근24시간 가격 변동률
                            self.dataFromAsset[asset][paymentCurrency][@"turnover24"] = turnover24; // 근24시간 거래대금
                            self.dataFromAsset[asset][paymentCurrency][@"volume24"] = volume24; // 근24시간 거래량
                        } else {
                            // 없으면 취급하지 않는 데이터로 예외처리해서 빼버리거나 예상치못한 형태의 데이터가 들어와서 예외처리 필요
                            // _를 포함한 값으로 symbol이 구성된 경우 (Bitget의 경우 모든 Futures 데이터가 이에 해당한다.)
                            if ([symbol containsString:@"USD_DMCBL_"]) {
                                // 유기한은 pass
                            } else {
                                // 예상 못한 오류 발생. 대응 필요.
                                NSLog(@"[WARN] Bitget Futures symbol is not normal. productType : %@, symbol : %@", productType, symbol);
                            }
                        }
                    }
                } else {
                    // ****** 비정상으로 실패시 ****** //
                    // 에러가 발생한 경우 retCode는 0이 아니며, retMsg에 관련 상세 내용이 있습니다.
                    NSLog(@"[ERROR] Bitget Futures Return Code : %@, Message : %@", jsonResponse[@"code"], jsonResponse[@"msg"]);
                    // api로 받은 데이터 깔끔한 dictionary로 가공하기
                }
            }
        }];
    }
}


// _paymentCurrencyInfo : spot, futures 각각에서 취급하는 paymentCurrencyList를 보유하게 됩니다. 해당 정보를 토대로, symbol 데이터를 활용해 asset과 paymentCurrency를 분리할 수 있습니다.
-(void) getOnlyPaymentCurrencyInfo {
    // bybit 관련 default 데이터 불러오기
    NSDictionary *bitget = [DefaultLoader sharedInstance].exchangeInfo[@"Bitget"];
    NSArray *categoryList = @[@"spot", @"futures"];
    // 데이터 정리하기
    for (NSString *category in categoryList) {
        _paymentCurrencyInfo[category] = [@[] mutableCopy];
        for (NSString *group in [bitget[category] allKeys]) {
            if ([bitget[category][group][@"category"] isEqual:category]) {
                // spot
                [_paymentCurrencyInfo[category] addObjectsFromArray:bitget[category][group][@"paymentCurrencyList"]];
            } else if ([bitget[category][group][@"category"] isEqual:@"coin-m"]) {
                // usd
                [_paymentCurrencyInfo[category] addObjectsFromArray:bitget[category][@"coinMargin"][@"paymentCurrencyList"]];
            } else if ([bitget[category][group][@"category"] isEqual:@"usd(s)-m"]) {
                // usdt
                [_paymentCurrencyInfo[category] addObjectsFromArray:bitget[category][@"stableMargin"][@"paymentCurrencyList"]];
            } else {
                NSLog(@"[WARN] Bitget Futures payment currency not match : Skip... -> bitget[category][group][@\"category\"] : %@", bitget[category][group][@"category"]);
            }
        }
    }
}

@end

 

 

 

 

 

6. AppDelegate에 앱 실행시 계속 작동되도록 데이터 업데이트 주기적으로 진행하는 소스코드 추가

 

// vim AppDelegate.h

#import <UIKit/UIKit.h>

// MARK: - [클래스 설명]
/*
// -----------------------------------------
1. 애플리케이션 딜리게이트 (선언부)
2. 전역변수 , 메소드 , 인스턴스변수 (클래스 생성자) 선언
// -----------------------------------------
*/



// -----------------------------------------
@interface AppDelegate : UIResponder <UIApplicationDelegate>
// -----------------------------------------

/* #################### 데이터 세팅 #################### */
// default.json의 exchangeInfo 저장
@property (strong, nonatomic) NSArray *exchangeListSpot;
@property (strong, nonatomic) NSArray *exchangeListFutures;

// MARK: [전역 변수 및 메소드 선언 부분]
/* #################### 메소드 #################### */
// 환율
-(void) updateRecentRatesData;
// 거래소별로 api call을 통한 데이터 업데이트 주기가 다르게 설정되어 분리
-(void) updateSpotDataBinance;
-(void) updateSpotDataBybit;
-(void) updateSpotDataBitget;
-(void) updateSpotDataOkx;
-(void) updateSpotDataKraken;

-(void) updateFuturesDataBybit;
-(void) updateFuturesDataBitget;



// -----------------------------------------
@end
// -----------------------------------------

 

// vim AppDelegate.m

#import "AppDelegate.h"

// 커스텀 셋 값 활용
#import "CustomizeSetting.h"
// price 정보 저장
#import "AllPriceLiveData.h"
// 환율 서비스
#import "ServiceRecentRates.h"
// default
#import "DefaultLoader.h"
// 거래소 api
#import "SpotBybit.h"
#import "SpotBinance.h"
#import "SpotBitget.h"
#import "SpotOkx.h"
#import "SpotKraken.h"
#import "FuturesBybit.h"
#import "FuturesBitget.h"



// MARK: - [헤더 [선언부] 호출]
@interface AppDelegate ()
@end
@implementation AppDelegate



// MARK: - [클래스 설명]
/*
// -----------------------------------------
1. 애플리케이션 딜리게이트 (구현부)
2. ios 13 이상 사용 : API_AVAILABLE(ios(13.0))
// -----------------------------------------
*/



// MARK: - [앱 프로세스 완료 및 앱 실행 실시]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions API_AVAILABLE(ios(13.0)){
    // 설명 :: 앱 프로세스 완료 및 앱 실행 실시
    NSLog(@"[AppDelegate >> didFinishLaunchingWithOptions]");
    
    // **************************************** [Start] active되어 enable된 exchange 정보 가져오기 **************************************** //
    // default.json의 필요한 exchange 기본 정보 데이터 가져오기
    DefaultLoader *exchangeInfo = [DefaultLoader sharedInstance];
    _exchangeListSpot = exchangeInfo.exchangeListSpot;
    _exchangeListFutures = exchangeInfo.exchangeListFutures;
    
    // **************************************** [Start] Spot 데이터 지속 업데이트 진행 로직 실행 **************************************** //
    
    /* #################### 최근 환율 정보 업데이트 #################### */
    // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
    [NSTimer scheduledTimerWithTimeInterval:1
                                     target:self
                                   selector:@selector(updateRecentRatesData)
                                   userInfo:nil
                                    repeats:YES];
    
    if ([_exchangeListSpot containsObject:@"Binance"]) {
        /* #################### Binance 바이낸스 #################### */
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_BINANCE
                                         target:self
                                       selector:@selector(updateSpotDataBinance)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Bybit 바이비트 #################### */
    if ([_exchangeListSpot containsObject:@"Bybit"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataBybit)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Bitget 비트겟 #################### */
    if ([_exchangeListSpot containsObject:@"Bitget"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataBitget)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Okx 오케이엑스 #################### */
    if ([_exchangeListSpot containsObject:@"Okx"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataOkx)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Kraken 크라켄 #################### */
    if ([_exchangeListSpot containsObject:@"Kraken"]) {
        // ** 2023-07-24 Kraken 미사용으로 변경 (because 최근 24시간 가격 변동률 정보 추출 불가) ** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataKraken)
                                       userInfo:nil
                                        repeats:YES];
    }
    
    // **************************************** [Start] Futures 데이터 지속 업데이트 진행 로직 실행 **************************************** //
    
    /* #################### 최근 환율 정보 업데이트 #################### */
    // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
    [NSTimer scheduledTimerWithTimeInterval:1
                                     target:self
                                   selector:@selector(updateRecentRatesData)
                                   userInfo:nil
                                    repeats:YES];
    
    /* #################### Bybit 바이비트 #################### */
    if ([_exchangeListFutures containsObject:@"Bybit"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateFuturesDataBybit)
                                       userInfo:nil
                                        repeats:YES];
    }
    
    if ([_exchangeListFutures containsObject:@"Bitget"]) {
        /* #################### Bitget 비트겟 #################### */
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_BINANCE
                                         target:self
                                       selector:@selector(updateFuturesDataBitget)
                                       userInfo:nil
                                        repeats:YES];
    }
    
    
    return YES;
}



// MARK: - [Scene 만들기 위한 구성 객체 반환 : 스토리보드 , info]
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0)){
    // 설명 :: Scene 만들기 위한 구성 객체 반환 : 스토리보드 , info
    NSLog(@"[AppDelegate >> configurationForConnecting]");
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}



// MARK: - [Scene 구성 객체 해제 실시]
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions API_AVAILABLE(ios(13.0)){
    // 설명 :: Scene 구성 객체 해제 실시
    NSLog(@"[AppDelegate >> didDiscardSceneSessions]");
}



// MARK: - [애플리케이션 사용자가 작업 태스크 날린 이벤트 감지]
- (void)applicationWillTerminate:(UIApplication *)application {
    // 설명 :: 애플리케이션 사용자가 작업 태스크 날린 이벤트 감지
    NSLog(@"[AppDelegate >> applicationWillTerminate]");
}




// **************************************** [Start] Spot 데이터 지속 업데이트 진행 로직 **************************************** //

/* #################### 환율 정보 업데이트 기본 시도 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateRecentRatesData {
    // ****** USDKRW 환율 정보 업데이트 ****** //
    ServiceRecentRates *ratesInfo = [ServiceRecentRates sharedInstance];
    [ratesInfo fetchData];
}

/* #################### Binance 바이낸스 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataBinance {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotBinance *mainData = [SpotBinance sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Binance"] = mainData.dataFromAsset;
}

/* #################### Bybit 바이비트 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataBybit {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotBybit *mainData = [SpotBybit sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Bybit"] = mainData.dataFromAsset;
}

/* #################### Bitget 비트겟 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataBitget {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotBitget *mainData = [SpotBitget sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Bitget"] = mainData.dataFromAsset;
}

/* #################### Okx 오케이엑스 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataOkx {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotOkx *mainData = [SpotOkx sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Okx"] = mainData.dataFromAsset;
}

// ** 2023-07-24 Kraken 미사용으로 변경 (because 최근 24시간 가격 변동률 정보 추출 불가) ** //
/* #################### Kraken 크라켄 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataKraken {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 가공하기
    SpotKraken *mainData = [SpotKraken sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Kraken"] = mainData.dataFromAsset;
}

// **************************************** [End] Spot 데이터 지속 업데이트 진행 로직 **************************************** //


// **************************************** [Start] Futures 데이터 지속 업데이트 진행 로직 **************************************** //

/* #################### Bybit 바이비트 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateFuturesDataBybit {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    FuturesBybit *mainData = [FuturesBybit sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentFuturesTicker[@"Bybit"] = mainData.dataFromAsset;
}

/* #################### Bitget 비트겟 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateFuturesDataBitget {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    FuturesBitget *mainData = [FuturesBitget sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentFuturesTicker[@"Bitget"] = mainData.dataFromAsset;
}


// **************************************** [End] Futures 데이터 지속 업데이트 진행 로직 **************************************** //


// -----------------------------------------
@end
// -----------------------------------------

 

 

 

 

 

 

+ Recent posts