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; } } }
static void QuerySellDetailForEmpty(string quote, string symbol, bool queryNear = false) { var notFillSellList = new SellInfoDao().ListNeedQuerySellDetail(quote, symbol); if (notFillSellList == null || notFillSellList.Count == 0) { return; } foreach (var item in notFillSellList) { try { if (!item.SellResult && item.SellOrderId == "-1") { continue; } if (queryNear && DateUtils.GetDate(item.SellCreateAt) < DateTime.Now.Date) { continue; } // 查询我的购买结果 var orderInfo = OkApi.QueryOrderDetail(item.SellClientOid, $"{item.Symbol}-{item.Quote}".ToUpper()); if (orderInfo == null) { continue; } Console.WriteLine($"QuerySellDetailForEmpty --> {quote}, {symbol} --> {JsonConvert.SerializeObject(orderInfo)}"); // 如果成交了。 if (orderInfo.status == "filled") { new SellInfoDao().UpdateNotFillSell(orderInfo); } else { new SellInfoDao().UpdateNotFillSellToCancel(orderInfo); } } catch (Exception ex) { logger.Error(ex.Message, ex); } } }
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); } } }
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); } }
static void Main(string[] args) { Console.WriteLine(1); // 注册日志 XmlConfigurator.Configure(new FileInfo("log4net.config")); Console.WriteLine(2); // 初始化币种 InstrumentsUtils.InitAllCoins(); Console.WriteLine(3); instruments = InstrumentsUtils.GetAll(); //DayAvgUtils.CalcAvgPrice(); // AccountDetailsUtils.ShowDetail(); //logger.Error(JsonConvert.SerializeObject(InstrumentsUtils.GetOkInstruments())); // 判断设置是否合理 //foreach (var item in instruments) //{ // // 获取行情, // var klineDataList = OkApi.GetKLineDataAsync(item.symbol + "-" + item.quote, "604800"); // if (klineDataList.Count == 0) // { // logger.Error($"获取行情数据有误 {item.quote},{item.symbol}"); // continue; // } // var close = klineDataList[0].close; // var max = klineDataList.Max(it => it.open); // var min = klineDataList.Min(it => it.low); // var avg = klineDataList.Sum(it => it.open) / klineDataList.Count; // if (close > item.MaxBuyPrice) // { // logger.Error($"现在价格大于MaxBuyPrice --> close:{close}, {item.quote}-{item.symbol} -- MaxBuyPrice: {item.MaxBuyPrice}"); // } // if (item.MaxBuyPrice > avg) // { // Console.WriteLine($"大于加权平均 --> avg:{avg}, {item.quote}-{item.symbol} -- MaxBuyPrice: {item.MaxBuyPrice}"); // } // if (item.MaxBuyPrice > max) // { // Console.WriteLine($"超过历史最大值 --> max:{max},min:{min}, {item.quote}-{item.symbol} -- MaxBuyPrice: {item.MaxBuyPrice}"); // } // else if (item.MaxBuyPrice > min + (max - min) * (decimal)0.7) // { // Console.WriteLine($"超过0.7 --> max:{max}, {item.quote}-{item.symbol}"); // } // Thread.Sleep(200); //} var orderDetailIndex = 0L; while (true) { orderDetailIndex++; var now = DateTime.Now; var btcPrice = (decimal)0; var ethPrice = (decimal)0; var okbPrice = (decimal)0; List <CoinInfo> allCoinInfos = new List <CoinInfo>(); try { allCoinInfos = new CoinInfoDao().ListCoinInfo(); var btcKlines = OkApi.GetKLineDataAsync("btc-usdt"); btcPrice = btcKlines[0].close; var ethKlines = OkApi.GetKLineDataAsync("eth-usdt"); ethPrice = ethKlines[0].close; var okbKlines = OkApi.GetKLineDataAsync("okb-usdt"); okbPrice = okbKlines[0].close; } catch (Exception ex) { logger.Error(ex.Message, ex); } // 获取所有ticks var tickers = OkApi.ListTickers(); foreach (var item in instruments) { // 查询订单结果 QueryOrderDetail(item.quote, item.symbol, (orderDetailIndex) % 10 != 0); // 找到当前的ticker var ticker = tickers.Find(it => it.instrument_id.ToLower() == $"{item.symbol}-{item.quote}".ToLower()); var needContinue = true; var oldData = new BuyInfoDao().List5LowerBuyForBuy(item.quote, item.symbol); if (oldData.Count == 0 || oldData[0].BuyPrice > ticker.last * (decimal)1.05) { needContinue = false; } if (needContinue) { var needSellForMoreList = new BuyInfoDao().ListNeedSellOrder(item.quote, item.symbol); if (needSellForMoreList.Count > 0 && needSellForMoreList[0].BuyPrice * (decimal)1.08 < ticker.last) { needContinue = false; } } if (needContinue) { // 读取数据库 看看以前的交易 var higherSell = new SellInfoDao().List5HigherSellForEmpty(item.quote, item.symbol); if (higherSell.Count > 0 && higherSell[0].SellPrice * (decimal)1.075 < ticker.last) { needContinue = false; } } if (needContinue) { var needBuyForEmptyList = new SellInfoDao().ListNeedBuyOrder(item.quote, item.symbol); if (needBuyForEmptyList.Count > 0 && needBuyForEmptyList[0].SellPrice > ticker.last * (decimal)1.075) { needContinue = false; } } if (needContinue && item.symbol.ToLower() != "egt") { continue; } // 查询订单结果 QueryOrderDetail(item.quote, item.symbol, false); // 核实订单 CheckOrderUtils.Check(item); // 获取行情, var klineDataList = OkApi.GetKLineDataAsync(item.symbol + "-" + item.quote); if (klineDataList == null || klineDataList.Count < 50) { logger.Error($"获取行情数据有误 {item.symbol}, quote:{item.quote}"); continue; } // 记录下价格 var findCoinfInfo = allCoinInfos.Find(it => it.Symbol == item.symbol); if (findCoinfInfo != null) { var nowPrice = (decimal)0;; if (item.quote.ToLower() == "btc") { nowPrice = klineDataList[0].close * btcPrice; } else if (item.quote.ToLower() == "eth") { nowPrice = klineDataList[0].close * ethPrice; } else if (item.quote.ToLower() == "okb") { nowPrice = klineDataList[0].close * okbPrice; } if (nowPrice > 0) { new CoinInfoDao().UpdateCoinInfo(item.symbol, nowPrice); } } if (runCount < 3) { var totalAmount = klineDataList.Sum(it => it.volume * (it.open + it.close) / 2); if (item.quote == "btc" && totalAmount < (decimal)0.01) { Console.WriteLine($"交易量太少, 不好办啊 {item.quote},{item.symbol}, totalAmount:{totalAmount}"); } if (item.quote == "eth" && totalAmount < 1) { Console.WriteLine($"交易量太少, 不好办啊 {item.quote},{item.symbol}, totalAmount:{totalAmount}"); } } if (item.MaxBuyPrice <= 0) { Console.WriteLine($"MaxBuyPrice -->没有设置 {item.quote}-{item.symbol} --> {klineDataList.Min(it => it.low)}"); } if (item.MaxBuyPrice > klineDataList[0].close * 4) { // 这里只是做粗略记录和控制 Console.WriteLine($"MaxBuyPrice xxxx -->设置的过大会接盘哦 {item.quote}-{item.symbol} --> {klineDataList.Min(it => it.low)}"); } try { // 启动交易 RunTrade(klineDataList, item); } catch (Exception ex) { logger.Error(ex.Message, ex); } // 每走一遍, 休眠一下 Thread.Sleep(500); } Console.WriteLine($"-------------> 运行次数:{runCount++}, 花费时间{(DateTime.Now - now).TotalSeconds} "); Thread.Sleep(1000 * 5); } }
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)}"); } } }