예제 #1
0
        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());
            }
        }
예제 #2
0
        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;
        }
예제 #3
0
        public ElwArbEach(
            KospiOptionInfo koi,
            List<ElwInfo> elwData,
            double strike,
            Account optionAccount,
            Account elwAccount,
            long maxOptionCountPerOnce,
            long maxOptionValuePerOnce,
            STR_ElwArb parent)
        {
            _KospiOptionInfo = koi;
            _elwData = elwData;
            _strike = strike;
            _optionAccount = optionAccount;
            _elwAccount = elwAccount;
            MaxOptionCountPerOnce = maxOptionCountPerOnce;
            _maxOptionValuePerOnce = maxOptionValuePerOnce;
            _parent = parent;

            Boolean bEnableReverse = true;
            _eaer = new ElwArbEachReverse(this, bEnableReverse);

            _eaecc = new ElwArbEachConditionChecker(this, _eaer, maxOptionCountPerOnce);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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;
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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;
        }
예제 #8
0
        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());
            }
        }
예제 #9
0
        public static KospiOptionInfo GetPreKospiOptionInfo(KospiOptionInfo cur)
        {
            if (cur == null)
            {
                return null;
            }

            DateTime maturity = Util.GetSystemOptionMaturity();
            double strike = GetPreStrike(cur.Strike);
            return OptionUtil.GetKOI(strike, cur.CallPut, maturity);
        }
예제 #10
0
        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();
            }
        }
예제 #11
0
        Boolean IsHighEnoughToPassNabi_Raw(
            KospiOptionInfo pre, 
            KospiOptionInfo cur, 
            KospiOptionInfo next,
            double fixedPrePrice,
            double fixedCurPrice,
            double fixedNextPrice)
        {
            if (pre == null || next == null || cur == null)
            {
                return false;
            }

            KospiOptionBoard board = null;

            if (pre.CallPut == CallPutFlag.Call)
            {
                board = RmdManager.Ins().Call;
            }
            else if (pre.CallPut == CallPutFlag.Put)
            {
                board = RmdManager.Ins().Put;
            }
            else
            {
                logger.Error("Invalid");
                Util.KillWithNotice("Invalid");
            }

            RawMarketData preRMD = board.GetData(pre.Code);
            RawMarketData curRMD = board.GetData(cur.Code);
            RawMarketData nextRMD = board.GetData(next.Code);

            if (!Util.IsValidRMDTimeAndPrice(preRMD) ||
                !Util.IsValidRMDTimeAndPrice(curRMD) ||
                !Util.IsValidRMDTimeAndPrice(nextRMD))
            {
                return false;
            }

            double prePrice = fixedPrePrice;
            double curPrice = fixedCurPrice;
            double nextPrice = fixedNextPrice;

            if (!Util.IsValidPrice(prePrice))
            {
                prePrice = preRMD.AskPrice1;
            }

            if (!Util.IsValidPrice(curPrice))
            {
                curPrice = curRMD.BidPrice1;
            }

            if (!Util.IsValidPrice(nextPrice))
            {
                nextPrice = nextRMD.AskPrice1;
            }

            // ELW를 BidPrice1으로 숏하고 양 옆의 옵션을 AskPrice1으로 롱해도 Arb이 되는 상황이다.
            if (curPrice * 2 >=  prePrice + nextPrice)
            {
                return true;
            }
            return false;
        }
예제 #12
0
        Boolean IsLowEnoughToPassNabiAsPre(KospiOptionInfo pre, double prePrice)
        {
            KospiOptionInfo cur = OptionUtil.GetNextKospiOptionInfo(pre);
            KospiOptionInfo next = OptionUtil.GetNextKospiOptionInfo(cur);

            return IsHighEnoughToPassNabi_Raw(pre, cur, next, prePrice, double.MaxValue, double.MaxValue);
        }
예제 #13
0
        Boolean IsLowEnoughToPassNabiAsNext(KospiOptionInfo next, double nextPrice)
        {
            KospiOptionInfo cur = OptionUtil.GetPreKospiOptionInfo(next);
            KospiOptionInfo pre = OptionUtil.GetPreKospiOptionInfo(cur);

            return IsHighEnoughToPassNabi_Raw(pre, cur, next, double.MaxValue, double.MinValue, nextPrice);
        }
예제 #14
0
        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;
        }
예제 #15
0
        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;
        }