public ElwArbReadyOrder(Account elwAccount, Account optionAccount) { try { this._elwAccount = elwAccount; this._optionAccount = optionAccount; List<double> strikes = OptionUtil.GetSortedStrikeList(CallPutFlag.Call); OptionTribe ot = null; foreach (double strike in strikes) { ot = ElwOptionUtil.GetOptionTribe(strike, CallPutFlag.Call); if (ot != null && ot.ElwInfos.Count > 0) { break; } } if (ot == null) { logger.Error("option tribe does not exist in ElwArbreadyOrder"); Util.KillWithNotice("option tribe does not exist in ElwArbreadyOrder"); } this._elwInfo = ot.ElwInfos[0]; if (this._elwInfo == null) { logger.Error("elw info does not exist in ElwArbreadyOrder"); Util.KillWithNotice("elw info does not exist in ElwArbreadyOrder"); } this._koi = ElwOptionUtil.GetKOIFromElwInfo(_elwInfo); if (this._koi == null) { logger.Error("koi info does not exist in ElwArbreadyOrder"); Util.KillWithNotice("koi info does not exist in ElwArbreadyOrder"); } this._elwLongPrice = 5; this._koiShortPrice = this._koi.UpLimit; } catch (System.Exception ex) { logger.Error(ex.ToString()); Util.KillWithNotice(ex.ToString()); } }
public static ElwOptionArbData GetElwOptionArbData( ElwInfo elw, RawMarketData rmdElw, KospiOptionInfo kospiOptionInfo, RawMarketData rmdOption, long maxCountOfOptionPerOnce, double maxValueOfOptionPerOnce, Account optionAccount, Account elwAccount, Boolean bForward, Boolean bAgressiveReverseOn, long totalAttemptOptionCount) { PreData data = GetPreData( elw, rmdElw, kospiOptionInfo, rmdOption, maxCountOfOptionPerOnce, maxValueOfOptionPerOnce, optionAccount, elwAccount, bForward, bAgressiveReverseOn, totalAttemptOptionCount); { ElwOptionArbData eoad = GetElwOptionArbData_WithProfit(data); if (eoad != null) { return eoad; } } { ElwOptionArbData eoad = GetElwOptionArbData_WO_Profit(data); if (eoad != null) { return eoad; } } return null; }
static Boolean IsCheapEnoughPassNabiTest(Boolean bForward, KospiOptionInfo koi, RawMarketData rmdElw, ElwInfo elw, long elwBookValue) { if (bForward) { // Long하려는 ELW가 싼지 결정해야 한다. double nextStrike = OptionUtil.GetNextStrike(koi.Strike); double nextStrike2 = OptionUtil.GetNextStrike(nextStrike); double preStrike = OptionUtil.GetPreStrike(koi.Strike); double preStrike2 = OptionUtil.GetPreStrike(preStrike); DateTime maturity = Util.GetSystemOptionMaturity(); KospiOptionInfo koiNext = OptionUtil.GetKOI(nextStrike, koi.CallPut, maturity); KospiOptionInfo koiNext2 = OptionUtil.GetKOI(nextStrike2, koi.CallPut, maturity); KospiOptionInfo koiPre = OptionUtil.GetKOI(preStrike, koi.CallPut, maturity); KospiOptionInfo koiPre2 = OptionUtil.GetKOI(preStrike2, koi.CallPut, maturity); if (koiNext == null || koiNext2 == null || koiPre == null || koiPre2 == null) { return false; } RawMarketData rmdNext = RmdManager.Ins().GetData(koiNext.Code); RawMarketData rmdNext2 = RmdManager.Ins().GetData(koiNext2.Code); RawMarketData rmdPre = RmdManager.Ins().GetData(koiPre.Code); RawMarketData rmdPre2 = RmdManager.Ins().GetData(koiPre2.Code); // Cur, Next, Next2로 나비 구성해본다. 나비 구성되면 true if (Util.IsValidRMDTimeAndPrice(rmdNext) && Util.IsValidRMDTimeAndPrice(rmdNext2)) { long left = ElwOptionUtil.GetOneOptionValueOfOption(rmdNext.BidPrice1) * 2; long right = ElwOptionUtil.GetOneOptionValueOfOption(rmdNext2.AskPrice1) + elwBookValue; if (left >= right) { return true; } } if (Util.IsValidRMDTimeAndPrice(rmdPre) && Util.IsValidRMDTimeAndPrice(rmdPre2)) { long left = ElwOptionUtil.GetOneOptionValueOfOption(rmdPre.BidPrice1) * 2; long right = ElwOptionUtil.GetOneOptionValueOfOption(rmdPre2.AskPrice1) + elwBookValue; if (left >= right) { return true; } } return false; } else { // Option Long, Elw Short인 상황 double nextStrike = OptionUtil.GetNextStrike(koi.Strike); double preStrike = OptionUtil.GetPreStrike(koi.Strike); if (koi == null) { return false; } DateTime maturity = Util.GetSystemOptionMaturity(); KospiOptionInfo koiNext = OptionUtil.GetKOI(nextStrike, koi.CallPut, maturity); KospiOptionInfo koiPre = OptionUtil.GetKOI(preStrike, koi.CallPut, maturity); if (koiNext == null || koiPre == null) { return false; } RawMarketData rmdNext = RmdManager.Ins().GetData(koiNext.Code); RawMarketData rmdPre = RmdManager.Ins().GetData(koiPre.Code); if (!Util.IsValidRMDTimeAndPrice(rmdNext) || !Util.IsValidRMDTimeAndPrice(rmdPre)) { return false; } long left = elwBookValue * 2; long right = ElwOptionUtil.GetOneOptionValueOfOption(rmdPre.AskPrice1) + ElwOptionUtil.GetOneOptionValueOfOption(rmdNext.AskPrice1); // ELW를 BidPrice1으로 숏하고 양 옆의 옵션을 AskPrice1으로 롱해도 Arb이 되는 상황이다. if (left >= right) { return true; } return false; } }
static PreData GetPreData( ElwInfo elw, RawMarketData rmdElw, KospiOptionInfo kospiOptionInfo, RawMarketData rmdOption, long maxCountOfOptionPerOnce, double maxValueOfOptionPerOnce, Account optionAccount, Account elwAccount, Boolean bForward, Boolean bAgressiveReverseOn, long totalAttemptOptionCount) { PreData data = new PreData(); // 기본 input data.Elw = elw; data.RmdElw = rmdElw; data.KOI = kospiOptionInfo; data.RmdOption = rmdOption; data.MaxCountOfOptionPerOnce = maxCountOfOptionPerOnce; data.MaxValueOfOptionPerOnce = maxValueOfOptionPerOnce; data.OptionAccount = optionAccount; data.ElwAccount = elwAccount; data.IsForward = bForward; data.IsAgressiveReverseOn = bAgressiveReverseOn; data.TotalAttemptOptionCount = totalAttemptOptionCount; // 가공 데이터 data.ElwPrice = bForward ? rmdElw.AskPrice1 : rmdElw.BidPrice1; data.ElwCount = bForward ? rmdElw.AskCount1 : rmdElw.BidCount1; data.ElwLS = bForward ? TradingDirection.Long : TradingDirection.Short; data.OptionPrice = bForward ? Math.Round(rmdOption.BidPrice1, 2) : Math.Round(rmdOption.AskPrice1, 2); data.OptionCount = bForward ? rmdOption.BidCount1 : rmdOption.AskCount1; data.OptionLS = bForward ? TradingDirection.Short : TradingDirection.Long; data.OptionCountOfElw = ElwOptionUtil.ConvertElwCountToOptionCount(elw, data.ElwCount); data.ElwOneOptionValue = ElwOptionUtil.GetOneOptionValueOfElw(elw, data.ElwPrice); data.OptionOneOptionValue = ElwOptionUtil.GetOneOptionValueOfOption(data.OptionPrice); data.Diff = data.OptionOneOptionValue - data.ElwOneOptionValue; if (!bForward) { data.Diff *= (-1); // forward가 아니라면 부호를 반대로 } return data; }
public ElwArbSweepUnit( KospiOptionInfo koi, ElwInfo elwInfo, long optionCount, POrder optionOrder, POrder elwOrder, STR_ElwArb parent) { try { // 이 생성자는 인수인계를 받을 때만 사용하도록 한다. // 주의한다. _state = State._5_Done; if (optionOrder.LongShort == elwOrder.LongShort) { logger.Error("OptionOrder, ElwOrder same trading direction"); Util.KillWithNotice("OptionOrder, ElwOrder same trading direction"); throw new Exception(); } OptionAccount = null; ElwAccount = null; long elwCount = ElwOptionUtil.ConvertOptionCountToElwCount(elwInfo, optionCount); OptionOrderGoal = new POrder( TradingDirection.Short, optionOrder.Code, optionCount, optionOrder.ReqPrice, optionOrder.TargetAccount, optionOrder.RMDClone, MarketType._3_Default, true); OptionOrderGoal.AddComment("ElwOptionSweeper.TakeOver.OptionOrderGoal"); OptionOrderGoal.UpdateForRemain(OptionOrderGoal.ReqCount, OptionOrderGoal.InitReqPrice); ElwOrderGoal = new POrder( TradingDirection.Long, elwOrder.Code, elwCount, elwOrder.ReqPrice, elwOrder.TargetAccount, elwOrder.RMDClone, MarketType._3_Default, true); ElwOrderGoal.AddComment("ElwOptionSweeper.TakeOver.ElwOrderGoal"); ElwOrderGoal.UpdateForRemain(ElwOrderGoal.ReqCount, ElwOrderGoal.InitReqPrice); ElwOrdersReal = new List<POrder>(); OptionOrdersReal = new List<POrder>(); POrder elwOrderReal = new POrder(ElwOrderGoal); elwOrderReal.AddComment("ElwOptionSweeper.TakeOver.elwOrderReal"); elwOrderReal.UpdateForRemain(elwOrderReal.ReqCount, elwOrderReal.InitReqPrice); ElwOrdersReal.Add(elwOrderReal); POrder optionOrderReal = new POrder(OptionOrderGoal); optionOrderReal.AddComment("ElwOptionSweeper.TakeOver.optionOrderReal"); optionOrderReal.UpdateForRemain(optionOrderReal.ReqCount, optionOrderReal.InitReqPrice); OptionOrdersReal.Add(optionOrderReal); _parent = parent; KOI = koi; Key = String.Format("{0};{1}", OptionOrderGoal.Code, ElwOrderGoal.Code); IsBodySweepQuickly = false; } catch (System.Exception ex) { logger.Error(ex.ToString()); Util.KillWithNotice(ex.ToString()); } }
Boolean EnterNewDoorOrder(ElwInfo targetElw, KospiOptionInfo targetKOI, KospiOptionInfo doorKOI) { try { const double kDownBarrier = 0.1; const double kMinBuffer = 0.5; RawMarketData targetOptionRMD = RmdManager.Ins().GetDataClone(targetKOI.Code); RawMarketData doorOptionRMD = RmdManager.Ins().GetDataClone(doorKOI.Code); if (!Util.IsValidPrice(targetOptionRMD.BidPrice1)) { return false; } if (!Util.IsValidPrice(doorOptionRMD.BidPrice1)) { return false; } if (doorOptionRMD.BidPrice1 <= kDownBarrier) { return false; } if (targetOptionRMD.BidPrice1 <= doorOptionRMD.BidPrice1) { logger.Warn("{0} {1} <= {2} {3}", targetOptionRMD.Code, targetOptionRMD.BidPrice1, doorOptionRMD.Code, doorOptionRMD.BidPrice1); return false; } String elwCode = targetElw.Code; double reqPrice = ElwOptionUtil.ConvertOptionPriceToElwPrice(targetElw, doorOptionRMD.BidPrice1); // same strike의 bidPrice - kMinBuffer 가격에 해당하는 price double reqPrice2 = ElwOptionUtil.ConvertOptionPriceToElwPrice(targetElw, Math.Max(0, targetOptionRMD.BidPrice1 - kMinBuffer)); // reference bidPrice와 target(같은 strike의 옵션)의 bidPrice - 0.5 중에 작은 값을 take reqPrice = Math.Min(reqPrice, reqPrice2); // 5원보다 작으면 정말 이상한 것이다. if (reqPrice < 4) { return false; } long reqCount = targetElw.MaxPossibleOrderCount; if (_parent.EnterMinCount) { reqCount = 10; // 테스트 경우 무조건 10개 주문 } Account account = _parent.Parent.ElwAccount; RawMarketData rmdElw = RmdManager.Ins().GetDataClone(elwCode); POrder o = new POrder(TradingDirection.Long, elwCode, reqCount, reqPrice, account, rmdElw); OrderLimitReferenceOOR limitReference = new OrderLimitReferenceOOR(OrderLimitReferenceOOR.OrderType.OOR, targetOptionRMD); o.LimitOrderReference = limitReference; POrderUtil.RequestOrder(o, this._orders); _parent.Parent.AddFishingOrder(o, STR_Door.FishingOrderType.Active); return true; } catch (System.Exception ex) { logger.Error(ex.ToString()); Util.KillWithNotice(ex.ToString()); } return false; }
void TakeOverPosition_Raw(KospiOptionInfo koi, ElwInfo elw, long optionCount, POrder optionOrder, POrder elwOrder) { ElwArbSweepUnit eos = new ElwArbSweepUnit(koi, elw, optionCount, optionOrder, elwOrder, _parent); logger.Info( "{0}\t{1}\t{2}\t ElwArbEach EOS is created...", koi.Code, elw.Code, optionCount.ToString("n0")); _lives.Add(eos); }
public ElwArbSweepUnit EnterPosition( ElwInfo elwInfo, String elwCode, TradingDirection elwLS, double elwPrice, long elwCount, RawMarketData rmdElw, TradingDirection optionLS, double optionPrice, long optionCount, RawMarketData rmdOption) { long optionEnterCount = optionCount; long elwEnterCount = elwCount; return EnterPosition_Raw( elwInfo, elwCode, elwLS, elwEnterCount, elwPrice, rmdElw, optionLS, optionCount, optionPrice, rmdOption); }
static double ConvertElwPriceToOptionPrice(ElwInfo elw, double elwPrice) { long elwCountOfOneOption = GetElwCountOfOneOption(elw.ChangeRate); return OptionUtil.RoundOptionPrice(elwPrice * elwCountOfOneOption / CommonConst._100_000); }
public static long ConvertElwCountToOptionCount(ElwInfo elw, long elwCount) { long elwCountOfOneOption = GetElwCountOfOneOption(elw.ChangeRate); long optionCount = (long)(elwCount / elwCountOfOneOption); return optionCount; }
public static long GetSignedParticleElwCount(ElwInfo elwInfo, List<POrder> orders) { long signedMaxPossibleExposureElwCount = 0; foreach (POrder o in orders) { if (o.Code.CompareTo(elwInfo.Code) == 0) { signedMaxPossibleExposureElwCount += POrderUtil.GetSignedMaxPossibleExposureCount(o); } } long elwCountOfOneOption = GetElwCountOfOneOption(elwInfo.ChangeRate); long particle = signedMaxPossibleExposureElwCount % elwCountOfOneOption; return particle; }
public static long ConvertElwCountTo100k(ElwInfo elw, long elwCount) { return elwCount * elw.ChangeRate; }
public static long GetOneOptionValueOfElw(ElwInfo elw, double elwPrice) { return (long)(elwPrice * GetElwCountOfOneOption(elw.ChangeRate)); }
public static KospiOptionInfo GetKOIFromElwInfo(ElwInfo ei) { DateTime maturity = Util.ConvertToDate(ei.Maturity); return OptionUtil.GetKOI(ei.Strike, ei.CallPut, maturity); }
public static double ConvertOptionPriceToElwPrice(ElwInfo elw, double optionPrice) { double marketValue = optionPrice * CommonConst._100_000; long elwCountOfOneOption = GetElwCountOfOneOption(elw.ChangeRate); double elwPrice = marketValue / elwCountOfOneOption; return ElwUtil.RoundElwPrice(elwPrice); }
public ElwOptionArbData( ElwInfo elw, double elwPrice, TradingDirection elwLS, KospiOptionInfo koi, double optionPrice, TradingDirection optionLS, long minOptionCount, long diff, RawMarketData rmdOption, RawMarketData rmdElw, Boolean bForward) { OptionCode = koi.Code; ElwCode = elw.Code; OptionCount = minOptionCount; ElwCount = ElwOptionUtil.ConvertOptionCountToElwCount(elw, minOptionCount); OptionPrice = optionPrice; ElwPrice = elwPrice; Elw = elw; Diff = diff; ElwLS = elwLS; OptionLS = optionLS; IsForward = bForward; Key = String.Format("{0};{1}", koi.Code, elw.Code); RmdOption = rmdOption; RmdElw = rmdElw; }
public static double ConvertElwCountToOptionCount_Double(ElwInfo elw, long elwCount) { long elwCountOfOneOption = GetElwCountOfOneOption(elw.ChangeRate); double optionCount = (double)elwCount / elwCountOfOneOption; return optionCount; }
static List<ElwInfo> LoadValidatedElwInfos() { List<ElwInfo> ret = new List<ElwInfo>(); DBManager dbManager = new DBManager(); MySqlConnection con = null; try { String ip = ConfigManager.Ins().Config.GetValue(ConfigKeyConst.DB_SERVER_IP); con = dbManager.CreateConnection(ip, CommonConst.DATABASE_MADVIPER); con.Open(); String query = "select * from validated_elw_list"; MySqlCommand cmd = new MySqlCommand(query, con); MySqlDataAdapter dataAdapter = new MySqlDataAdapter(cmd); DataSet ds = new DataSet("validated_elw_list"); dataAdapter.Fill(ds, "validated_elw_list"); DataRowCollection drc = ds.Tables["validated_elw_list"].Rows; if (drc.Count <= 0) { return ret; } for (int i = 0; i < drc.Count; ++i) { DataRow dr = drc[i]; String code = dr["code"].ToString(); String name = dr["name"].ToString(); long maturity = Convert.ToInt64(dr["maturity"]); double strike = Convert.ToDouble(dr["strike"]); int changeRate = Convert.ToInt32(dr["change_rate"]); String callPut = dr["call_put"].ToString(); long issuedCount = Convert.ToInt64(dr["issued_count"]); ElwInfo ei = new ElwInfo(); ei.Code = code; ei.Name = name; ei.Maturity = maturity; ei.Strike = strike; ei.ChangeRate = changeRate; ei.CallPut = callPut.CompareTo("Call") == 0 ? CallPutFlag.Call : CallPutFlag.Put; ei.IssuedCount = issuedCount; ei.IsValidated = true; ret.Add(ei); } ds.Clear(); } catch (System.Exception ex) { logger.Error(ex.ToString()); Util.KillWithNotice(ex.ToString()); } finally { dbManager.Close(con); } return ret; }
ElwArbSweepUnit EnterPosition_Raw( ElwInfo elwInfo, String elwCode, TradingDirection elwLS, long elwEnterCount, double elwPrice, RawMarketData rmdElw, TradingDirection optionLS, long optionEnterCount, double optionPrice, RawMarketData rmdOption) { POrder optionOrder = null; POrder elwOrder = null; try { { // ELW Long // 우선 ELW Long을 진행하도록 한다. Detail.ProductType pt = ProductUtil.Ins().GetProductType(elwCode); if (pt != Detail.ProductType.ELW) { logger.Error( "CRITICAL ERROR!!! 엄청 무서운 일이 벌어졌다. ELW가 아닌 {0} 종목이 {1} 가격에 {2} 개 사려고 했다.", elwCode, elwPrice, elwEnterCount); Util.KillWithNotice("error"); _bFinish = true; return null; } else { // ELW 롱 elwOrder = new POrder(elwLS, elwCode, elwEnterCount, elwPrice, _elwAccount, rmdElw); elwOrder.AddComment("EAE.EnterPosition_Raw.elwOrder"); elwOrder.Free(); if (!POrderLegalManager.Ins().IsLegalOrder(elwOrder, false)) { return null; } } } { // 옵션 숏 // 그럴리 없겠지만 무서우니까 최종적으로 확인을 한번 더 해보자. Detail.ProductType pt = ProductUtil.Ins().GetProductType(_KospiOptionInfo.Code); if (pt != Detail.ProductType.CallOption && pt != Detail.ProductType.PutOption) { logger.Error( "CRITICAL ERROR!!! 엄청 무서운 일이 벌어졌다. 옵션도 아닌 {0} 종목이 {1} 가격에 {2} 개 사려고 했다.", _KospiOptionInfo.Code, optionPrice, optionEnterCount); Util.KillWithNotice("CRITICAL ERROR!!!"); _bFinish = true; return null; } else { optionOrder = new POrder(optionLS, _KospiOptionInfo.Code, optionEnterCount, optionPrice, _optionAccount, rmdOption); optionOrder.AddComment("EAE.EnterPosition_Raw.optionOrder"); optionOrder.Free(); if (!POrderLegalManager.Ins().IsLegalOrder(optionOrder, false)) { return null; } } } if (optionOrder != null && elwOrder != null) { ElwArbSweepUnit eos = new ElwArbSweepUnit( _KospiOptionInfo, elwInfo, _optionAccount, optionOrder, _elwAccount, elwOrder, _parent, MonitoringEndDate); return eos; } else { logger.Error("Unexpected"); Util.KillWithNotice("Unexpected"); } } catch (System.Exception ex) { logger.Error(ex.ToString()); Util.KillWithNotice(ex.ToString()); } return null; }
public ElwArbSweepUnit( KospiOptionInfo koi, ElwInfo elwInfo, Account optionAccount, POrder optionOrder, Account elwAccount, POrder elwOrder, STR_ElwArb parent, DateTime dtEnd) { try { KOI = koi; CurID = ++ID_GENERATOR; OptionAccount = optionAccount; OptionOrderGoal = optionOrder; OptionOrderGoal.AddComment("EOS Constructor"); ElwAccount = elwAccount; ElwOrderGoal = elwOrder; ElwOrderGoal.AddComment("EOS Constructor"); _elwInfo = elwInfo; OptionOrdersReal = new List<POrder>(); ElwOrdersReal = new List<POrder>(); _state = State._1_MuteFewSecs; Key = String.Format("{0};{1}", OptionOrderGoal.Code, ElwOrderGoal.Code); ShowState(); _mute = new Timer(ENTER_POSITION_MUTE, ""); RequestInitOrder(ElwOrderGoal, ElwOrdersReal); _parent = parent; _parent.IncreaseEnteredArbCount(KOI.Code, OptionOrderGoal.ReqCount); _dtEnd = dtEnd; IsBodySweepQuickly = false; } catch (System.Exception ex) { logger.Error(ex.ToString()); Util.KillWithNotice(ex.ToString()); } finally { ElwAccount.DiffFastExactPossibleShortCount(ElwOrderGoal.Code, "ElwOptionSweeper 생성자"); OptionOrderGoal.Free(); optionOrder.Free(); ElwOrderGoal.Free(); elwOrder.Free(); } }
public void Load() { if (_bLoaded) { return; } _bLoaded = true; Dictionary<String, ElwInfo> elwInfos = new Dictionary<string, ElwInfo>(); Dictionary<String, String> codeMap = new Dictionary<string, string>(); DateTime dtElwMaturity = Util.GetSystemOptionMaturity(); logger.Info("Elw maturity is ({0}) loaded from CONFIG", dtElwMaturity); LoadingData_Elw loadingData = GetLoadingData(dtElwMaturity); foreach (CP_LoadingDatum_Elw datum in loadingData.Data) { String underlyingCode = datum.UnderlyingCode; String underlyingName = datum.UnderlyingName; String code = datum.Code; String name = datum.Name; String callPut = datum._CallPut; long maturity = datum.Maturity; double strike = datum.Strike; int changeRate = datum.ChangeRate; double bidPrice = datum.BidPrice; double askPrice = datum.AskPrice; double curPrice = datum.CurPrice; double gearing = datum.Gearing; long issuedCount = datum.IssuedCount; long remainDays = datum.RemainDays; String longCode = datum.LongCode; ElwInfo data = new ElwInfo(); data.UnderlyingCode = underlyingCode; data.UnderlyingName = underlyingName; data.Name = name; data.Code = code; data.RemainDays = remainDays; data.IssuedCount = issuedCount; data.MaxPossibleOrderCount = ElwUtil.RoundElwCount((long)(issuedCount * 0.05)); data.YesterdayLastPrice = curPrice; if (callPut.CompareTo("콜") == 0) { data.CallPut = CallPutFlag.Call; } else if (callPut.CompareTo("풋") == 0) { data.CallPut = CallPutFlag.Put; } else { logger.Error("Unexpected"); Util.KillWithNotice("Unexpected"); } data.Maturity = maturity; data.Strike = Math.Round(strike, 2); data.ChangeRate = changeRate; if (data.ChangeRate != 200 && data.ChangeRate != 100 && data.ChangeRate != 50 && data.ChangeRate != 25 && data.ChangeRate != 80 && data.ChangeRate != 40) { logger.Warn(String.Format("{0} has {1} change rate (discard from ArbList)", code, changeRate)); continue; } // 일단 Validated 하지 않다. DB와 비교를 통해서 검증한다. data.IsValidated = false; elwInfos.Add(code, data); codeMap.Add(longCode, code); if (longCode.Length == 0) { logger.Error("CRITICAL ERROR Can't create longCode!!! {0}", code); Util.KillWithNotice("CRITICAL ERROR Can't create longCode!!!"); } RmdManager.Ins().Register(code, name, Detail.ProductType.ELW); } ElwUtil.SetInfo(elwInfos, codeMap); logger.Info("({0:n0} / {1:n0}) Elw load", elwInfos.Count, loadingData.Data.Count); }
Boolean CancelDangerousOrders_Raw(POrder order, ElwInfo targetElw, KospiOptionInfo targetKOI, KospiOptionInfo doorKOI) { try { const double kBuffer = 0.3; RawMarketData targetOptionRMD = RmdManager.Ins().GetDataClone(targetKOI.Code); RawMarketData doorOptionRMD = RmdManager.Ins().GetDataClone(doorKOI.Code); Boolean bTargetRMDBidPriceValid = Util.IsValidPrice(targetOptionRMD.BidPrice1); Boolean bDoorRMDBidPriceValid = Util.IsValidPrice(doorOptionRMD.BidPrice1); if (!bTargetRMDBidPriceValid && !bDoorRMDBidPriceValid) { // 둘다 값이 없으면 위험해 보인다. 이런 경우에는 취소를 한다. return true; } if (bDoorRMDBidPriceValid) { // reference를 바로 옆 옵션으로 했다. // 바로 옆 옵션 가격보다 높은 가격으로 reqPrice했다면 위험한 상태이다. double elwPriceOfOption = ElwOptionUtil.ConvertOptionPriceToElwPrice(targetElw, doorOptionRMD.BidPrice1); if (elwPriceOfOption <= order.ReqPrice) { return true; } else { return false; } } else if (bTargetRMDBidPriceValid) { // target이 있다면 target BidPrice - kBuffer < reqPrice라면 위험한 상태이다. double elwPriceOfOption = ElwOptionUtil.ConvertOptionPriceToElwPrice(targetElw, Math.Max(0, targetOptionRMD.BidPrice1 - kBuffer)); if (elwPriceOfOption <= order.ReqPrice) { return true; } else { return false; } } else { return false; } } catch (System.Exception ex) { logger.Error(ex.ToString()); Util.KillWithNotice(ex.ToString()); } return true; }