Beispiel #1
0
        static void PrepareSellForMore(List <KLineData> coinInfos, TradeItem tradeItem)
        {
            string quote  = tradeItem.quote;
            string symbol = tradeItem.symbol;
            // 判断是否交易。
            var needSellOldData = new BuyInfoDao().ListNeedSellOrder(quote, symbol);

            foreach (var item in needSellOldData)
            {
                if (item.BuyStatus != "filled")
                {
                    continue;
                }
                // 这里的策略真的很重要
                // 如果超过20%, 则不需要考虑站稳, 只要有一丁点回调就可以
                // 如果超过7%, 站稳则需要等待3个小时
                if (coinInfos[0].close < item.BuyPrice * (decimal)1.09)
                {
                    continue;
                }

                // 找到最大的close
                var maxClose       = coinInfos.Max(it => it.close);
                var percent        = coinInfos[0].close / item.BuyPrice; // 现在的价格/购买的价格
                var huidiaoPercent = 1 + (percent - 1) / 10;
                if (coinInfos[0].close * (decimal)1.03 < maxClose || coinInfos[0].close * huidiaoPercent < maxClose)
                {
                    Console.WriteLine($"PrepareSell --> {item.Quote}--{item.Symbol}----");
                    // 出售, 适当的回调,可以出售
                    DoSellForMore(item, coinInfos[0].close);
                }
            }
        }
Beispiel #2
0
        public static decimal GetAvgPrice(TradeItem item, string granularity)
        {
            var klineDataList = OkApi.GetKLineDataAsync(item.symbol + "-" + item.quote, granularity);

            if (klineDataList == null)
            {
                return(0);
            }
            var count      = 0;
            var totalPrice = (decimal)0;

            foreach (var data in klineDataList)
            {
                var dataItemPrice = (data.open + data.close) / 2;

                totalPrice += dataItemPrice;
                count++;
            }

            //
            var avgPrice = totalPrice / count;

            avgPrice = decimal.Round(avgPrice, 8);
            return(avgPrice);
        }
Beispiel #3
0
 public static void Check(TradeItem tradeItem)
 {
     try
     {
         DoCheck(tradeItem);
     }
     catch (Exception ex)
     {
         logger.Error(ex.Message, ex);
     }
 }
Beispiel #4
0
        static void RunTrade(List <KLineData> coinInfos, TradeItem tradeItem)
        {
            // 做多购买
            PrepareBuyForMore(coinInfos, tradeItem);

            // 多单收割
            PrepareSellForMore(coinInfos, tradeItem);

            // 做空出售
            PrepareSellForEmpty(coinInfos, tradeItem);

            // 做空购买
            PrepareBuyForEmpty(coinInfos, tradeItem);
        }
Beispiel #5
0
        static void PrepareSellForEmpty(List <KLineData> coinInfos, TradeItem tradeItem)
        {
            if (tradeItem.SmallSellPrice <= 0 || tradeItem.EmptySize <= 0)
            {
                return;
            }

            string  quote    = tradeItem.quote;
            string  symbol   = tradeItem.symbol;
            decimal nowPrice = coinInfos[0].close;
            // 读取数据库 看看以前的交易
            var oldData = new SellInfoDao().List5HigherSellForEmpty(quote, symbol);
            // 判断是否阶梯
            var bigTheSellPrice = false;

            if (oldData.Count > 0)
            {
                var rateDecimal = (decimal)1.088;
                bigTheSellPrice = nowPrice > oldData[0].SellPrice * rateDecimal;
                if (oldData[0].SellTradePrice > 0 && oldData[0].SellTradePrice >= oldData[0].SellPrice)
                {
                    bigTheSellPrice = nowPrice > oldData[0].SellTradePrice * rateDecimal;
                }
            }
            if (oldData.Count == 0 || bigTheSellPrice)
            {
                // coinfInfos的最高价和最低价相差不能太大
                var min = coinInfos.Min(it => it.low);
                var max = coinInfos.Max(it => it.high);
                if (tradeItem.SmallSellPrice > 0 && nowPrice < tradeItem.SmallSellPrice)
                {
                    // logger.Error($"价格过低,不能售出 quote: {quote}, symbol:{symbol}");
                    return;
                }
                // 是否超过了最小售价
                if (InstrumentsUtils.CheckSmallSellPrice(quote, symbol, coinInfos[0].close))
                {
                    // 出售一单
                    Console.WriteLine($"PrepareSellForEmpty --> {quote}, {symbol}");
                    if (oldData.Count > 0)
                    {
                        logger.Error($"相差间隔 lastPrice: {oldData[0].Id} -- {oldData[0].SellTradePrice}, nowPrice:{nowPrice}, rate: {(oldData[0].SellTradePrice == 0 ? 0 : (nowPrice / oldData[0].SellTradePrice))} --  { oldData[0].SellTradePrice / nowPrice}");
                    }
                    DoSellForEmpty(tradeItem, nowPrice);
                    return;
                }
            }
        }
Beispiel #6
0
        static void PrepareBuyForEmpty(List <KLineData> coinInfos, TradeItem tradeItem)
        {
            string quote  = tradeItem.quote;
            string symbol = tradeItem.symbol;
            // 判断是否交易。
            var needBuyOldData = new SellInfoDao().ListNeedBuyOrder(quote, symbol);

            if (needBuyOldData.Count > 0)
            {
                Console.WriteLine($"----------> {quote} {symbol} 空: {needBuyOldData.Count}");
            }
            foreach (var item in needBuyOldData)
            {
                if (item.SellStatus != "filled")
                {
                    continue;
                }
                // 这里的策略真的很重要
                // 如果超过20%, 则不需要考虑站稳, 只要有一丁点回调就可以
                // 如果超过7%, 站稳则需要等待3个小时
                if (coinInfos[0].close * (decimal)1.09 > item.SellPrice)
                {
                    continue;
                }

                // 找到最大的close
                var minClose       = coinInfos.Min(it => it.close);
                var percent        = item.SellPrice / coinInfos[0].close; // 现在的价格/出售的价格
                var huidiaoPercent = 1 + (percent - 1) / 10;
                if (coinInfos[0].close > minClose * (decimal)1.03 || coinInfos[0].close > minClose * huidiaoPercent)
                {
                    Console.WriteLine($"PrepareBuyForEmpty --> {item.Quote}--{item.Symbol}----");
                    // 出售, 适当的回调,可以购入
                    DoBuyForEmpty(item, coinInfos[0].close);
                }
            }
        }
Beispiel #7
0
        static void DoSellForEmpty(TradeItem tradeItem, decimal nowPrice)
        {
            string quote  = tradeItem.quote;
            string symbol = tradeItem.symbol;

            if (lastSellForEmptyDate > DateTime.Now.AddSeconds(-20))
            {
                // 如果20秒内做空过一单, 则不能再次做空
                return;
            }

            var sellSize = tradeItem.EmptySize;

            if (sellSize <= 0)
            {
                return;
            }

            var count = new SellInfoDao().GetNotBuyCount(quote, symbol);

            count = Math.Min(count, 60);

            sellSize = sellSize * (1 + count / (decimal)30);
            var sellPrice = nowPrice / (decimal)1.01;

            var okInstrument = InstrumentsUtils.GetOkInstruments(quote, symbol);

            sellPrice = decimal.Round(sellPrice, okInstrument.GetTickSizeNumber());
            sellSize  = decimal.Round(sellSize, okInstrument.GetSizeIncrementNumber());

            var client_oid = "sell" + DateTime.Now.Ticks;

            try
            {
                logger.Error($"");
                logger.Error($"1: 准备出售(空) {quote}-{symbol}, client_oid:{client_oid},  nowPrice:{nowPrice}, sellPrice:{sellPrice.ToString()}, sellSize:{sellSize.ToString()}");
                var tradeResult = OkApi.Sell(client_oid, symbol + "-" + quote, sellPrice.ToString(), sellSize.ToString());
                logger.Error($"2: 下单完成 {JsonConvert.SerializeObject(tradeResult)}");

                new SellInfoDao().CreateSellInfo(new SellInfo
                {
                    SellClientOid      = client_oid,
                    SellPrice          = sellPrice,
                    SellQuantity       = sellSize,
                    SellCreateAt       = DateTime.Now.ToString("yyyy-MM-dd"),
                    SellFilledNotional = (decimal)0,
                    SellStatus         = "prepare",
                    SellOrderId        = tradeResult.order_id,
                    SellResult         = tradeResult.result,

                    Quote    = quote,
                    Symbol   = symbol,
                    UserName = "******"
                });
                logger.Error($"3: 添加记录完成");
                logger.Error($"");

                lastSellForEmptyDate = DateTime.Now;
            }
            catch (Exception e)
            {
                logger.Error("做空出售异常 严重 --> " + e.Message, e);
                Thread.Sleep(1000 * 60 * 10);
            }
        }
Beispiel #8
0
        static void PrepareBuyForMore(List <KLineData> coinInfos, TradeItem tradeItem)
        {
            string  quote    = tradeItem.quote;
            string  symbol   = tradeItem.symbol;
            decimal nowPrice = coinInfos[0].close;
            // 读取数据库 看看以前的交易
            var oldData = new BuyInfoDao().List5LowerBuyForBuy(quote, symbol);

            if (tradeItem.symbol.ToLower() == "egt" && tradeItem.quote.ToLower() == "okb")
            {
                logger.Error($"egt 数量: {oldData.Count}, {new DateTime(2019, 6, 12)}");
                oldData.RemoveAll(it => DateUtils.GetDate(it.BuyCreateAt) < new DateTime(2019, 6, 12));
                logger.Error($"egt 剩余数量: {oldData.Count}");
            }
            // 判断是否阶梯
            var smallThenBuyPrice = false;

            if (oldData.Count > 0)
            {
                var rateDecimal = (decimal)1.078;
                if (tradeItem.quote.ToLower() == "okb")
                {
                    rateDecimal = (decimal)1.05;
                }

                if (tradeItem.BuyLadderRatio > (decimal)1.066)
                {
                    rateDecimal = tradeItem.BuyLadderRatio;
                }

                smallThenBuyPrice = nowPrice * rateDecimal < oldData[0].BuyPrice;
                if (oldData[0].BuyTradePrice > 0 && oldData[0].BuyTradePrice <= oldData[0].BuyPrice)
                {
                    smallThenBuyPrice = nowPrice * rateDecimal < oldData[0].BuyTradePrice;
                }
            }
            if (oldData.Count == 0 || smallThenBuyPrice)
            {
                // coinfInfos的最高价和最低价相差不能太大
                var min = coinInfos.Min(it => it.low);
                var max = coinInfos.Max(it => it.high);
                if (tradeItem.MaxBuyPrice > 0 && nowPrice > tradeItem.MaxBuyPrice)
                {
                    logger.Error($"价格过高,不能购入 quote: {quote}, symbol:{symbol}");
                }
                else
                {
                    // 是否超过了最大限价
                    if (max < 2 * min && InstrumentsUtils.CheckMaxBuyPrice(quote, symbol, coinInfos[0].close))
                    {
                        // 购买一单
                        Console.WriteLine($"PrepareBuy --> {quote}, {symbol}");
                        if (oldData.Count > 0)
                        {
                            logger.Error($"相差间隔 lastPrice: {oldData[0].Id} -- {oldData[0].BuyTradePrice}, nowPrice:{nowPrice}, rate: {(oldData[0].BuyTradePrice == 0 ? 0 : (nowPrice / oldData[0].BuyTradePrice))} --  { oldData[0].BuyTradePrice / nowPrice}");
                        }
                        DoBuyForMore(quote, symbol, nowPrice);
                        return;
                    }
                }
            }
        }
Beispiel #9
0
        public static void DoCheck(TradeItem tradeItem)
        {
            var instrument = $"{tradeItem.symbol}-{tradeItem.quote}".ToUpper();

            // 核实下 最近 10个小时是否统计过,
            if (lastCheckDate > DateTime.Now.AddMinutes(-1))
            {
                // 最近1分钟有核实过, 则不再核实
                return;
            }
            if (lastCheckDateDic.ContainsKey(instrument) && lastCheckDateDic[instrument] > DateTime.Now.AddHours(-12))
            {
                // 这个交易对, 12个小时内核实过,则不再核实
                return;
            }
            else
            {
                if (lastCheckDateDic.ContainsKey(instrument))
                {
                    lastCheckDateDic[instrument] = DateTime.Now;
                }
                else
                {
                    lastCheckDateDic.Add(instrument, DateTime.Now);
                }
            }

            lastCheckDate = DateTime.Now;


            var orderList = OkApi.ListFilledOrder(instrument);

            Console.WriteLine($"需要核实的订单数据:{orderList.Count}");
            foreach (var order in orderList)
            {
                if (order.side == "buy")
                {
                    // 列出数据库里面的交易记录, 对比一下。
                    var orderInDb  = new BuyInfoDao().GetBuyOrder(order.client_oid);
                    var orderInDb2 = new SellInfoDao().GetBuyOrder(order.client_oid);
                    if ((
                            orderInDb == null ||
                            orderInDb.BuyClientOid != order.client_oid ||
                            orderInDb.BuyCreateAt != order.created_at ||
                            orderInDb.BuyStatus != order.status ||
                            orderInDb.BuyOrderId != order.order_id
                            )
                        &&
                        (
                            orderInDb2 == null ||
                            orderInDb2.BuyClientOid != order.client_oid ||
                            orderInDb2.BuyCreateAt != order.created_at ||
                            orderInDb2.BuyStatus != order.status ||
                            orderInDb2.BuyOrderId != order.order_id
                        ))
                    {
                        logger.Error($"有个订单不合理,快速查看一下 begin");
                        logger.Error($"{JsonConvert.SerializeObject(order)}");
                        logger.Error($"{JsonConvert.SerializeObject(orderInDb)}");
                        logger.Error($"{JsonConvert.SerializeObject(orderInDb2)}");
                        logger.Error($"有个订单不合理,快速查看一下 end ");
                    }
                }
                else if (order.side == "sell")
                {
                    // 列出数据库里面的交易记录, 对比一下。
                    var orderInDb  = new BuyInfoDao().GetSellOrder(order.client_oid);
                    var orderInDb2 = new SellInfoDao().GetSellOrder(order.client_oid);
                    if ((
                            orderInDb == null ||
                            orderInDb.SellClientOid != order.client_oid ||
                            orderInDb.SellCreateAt != order.created_at ||
                            orderInDb.SellStatus != order.status ||
                            orderInDb.SellOrderId != order.order_id
                            )
                        &&
                        (
                            orderInDb2 == null ||
                            orderInDb2.SellClientOid != order.client_oid ||
                            orderInDb2.SellCreateAt != order.created_at ||
                            orderInDb2.SellStatus != order.status ||
                            orderInDb2.SellOrderId != order.order_id
                        ))
                    {
                        logger.Error($"有个订单不合理,快速查看一下 begin");
                        logger.Error($"{JsonConvert.SerializeObject(order)}");
                        logger.Error($"{JsonConvert.SerializeObject(orderInDb)}");
                        logger.Error($"{JsonConvert.SerializeObject(orderInDb2)}");
                        logger.Error($"有个订单不合理,快速查看一下 end ");
                    }
                }
                else
                {
                    logger.Error($"数据统计不正确, 不存在的side");
                    Console.WriteLine($"{JsonConvert.SerializeObject(order)}");
                }
            }
        }