public WSMonitorada(Usuario user, ServerConfig config) { this.User = user; OneSignalApi = new OneSignalAPI(config.OneSignalToken, config.AppServer, config.OneSignalAppId); if (!string.IsNullOrEmpty(user.BinanceAPIKey) && !string.IsNullOrEmpty(user.BinanceAPISecret)) { timerKeepAlive.Interval = TimeSpan.FromMinutes(15).TotalMilliseconds; timerKeepAlive.Elapsed += (object source, ElapsedEventArgs e) => { BinanceUserDataStream.KeepAlive(user.BinanceAPIKey, user.BinanceAPISecret); }; timerKeepAlive.Start(); // a cada 3 horas verifica se o cara possui ordem aberta se nao possuir desconecta ele closeconnection.Interval = TimeSpan.FromHours(1).TotalMilliseconds; closeconnection.Elapsed += (object source, ElapsedEventArgs e) => { using (var _OrdemRepo = new OrdemRepository()) { var ordensabertas = _OrdemRepo.OrdemsAbertas(User.Id); if (ordensabertas.Count == 0) { this.Dispose(true); } } }; closeconnection.Start(); var result = BinanceUserDataStream.GetListenKey(user.BinanceAPIKey, user.BinanceAPISecret); if (result.IsSuccessStatusCode) { var res = result.Content.ReadAsStringAsync().Result; var listenKey = (string)JsonConvert.DeserializeObject <dynamic>(res).listenKey; ws = new WebSocket("wss://stream.binance.com:9443/ws/" + listenKey); //ws.Log.Level = LogLevel.Trace; //ws.Log.File = "C:\\LogConexao\\" + user.nome + ".txt"; //Para envio de ping ws.EmitOnPing = true; ws.OnOpen += (sender, e) => { }; ws.OnMessage += (sender, e) => { if (e.IsPing) { ws.Ping(); return; } var content = e.Data; var ws_Payload = JsonConvert.DeserializeObject <dynamic>(content); //if (ws_Payload.e != "outboundAccountInfo") //{ // Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (" + ws_Payload.e + ") Payloadobjeto => " + ws_Payload); //} using (var _OrdemRepo = new OrdemRepository()) { if ((string)ws_Payload.e == "executionReport") { //Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (ExecutionReport) => " + (string)ws_Payload.x + " => " + e.Data); //Ordem Executada if ((string)ws_Payload.x == "TRADE" && (string)ws_Payload.X == "FILLED") { string ordemID = (string)ws_Payload.c; var ordem = _OrdemRepo.EntradaByBinanceOrderID(ordemID); //tentar passar o id pra inteiro significa q a ordem foi gerada no meu sistema, o sisteman binance gera uma string #region OrderEntrada if (ordem != null && ordem.TipoOrdem_Id == 1) { Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (Ordem Entrada Executada) OrdemId => " + ordemID); using (var _OrderCommision = new OrdemComissionRepository()) { var Comission = new OrdemComission { Order_Id = ordem.Id, ComissionAmount = (decimal)ws_Payload.n, ComissionAsset = (string)ws_Payload.N, QtdExecutada = (decimal)ws_Payload.z, ValorExecutado = (decimal)ws_Payload.p }; _OrderCommision.Add(Comission); ordem.DataEntrada = DateTime.UtcNow; ordem.OrdemStatus_Id = 3; ordem.BinanceStatus_Id = 3; _OrdemRepo.Update(ordem); _OrdemRepo.AddReference(ordem, "OrdemStatus"); signalContext.Clients.User(user.Id.ToString()).EntradaRealizada(ordem); string LimitOrderID, StopOrderID; do { LimitOrderID = Helper.GenerateRandomOcoOrderID(10); } while (_OrdemRepo.IsValidOrderID(LimitOrderID)); do { StopOrderID = Helper.GenerateRandomOcoOrderID(10); } while (_OrdemRepo.IsValidOrderID(StopOrderID)); var listAssets = _OrderCommision.GetOrderComissions(ordem.Id); decimal SaldoQuantidade = Helper.ArredondarQuantidadeVenda(listAssets, ordem); var limitLoss = Helper.OcoStopLimitWithPercent(ordem.Chamada.Symbol_id, ordem.Chamada.PrecoLoss, 0.5m); var ocoReturn = BinanceRestApi.SendSaidaOco(user.BinanceAPIKey.Trim(), user.BinanceAPISecret.Trim(), ordem.Chamada.Symbol.symbol, SaldoQuantidade, ordem.Chamada.PrecoGain, ordem.Chamada.PrecoLoss, limitLoss, LimitOrderID, StopOrderID); if (ocoReturn.IsSuccessStatusCode) { var ocoRes = ocoReturn.Content.ReadAsStringAsync().Result; var ocoObj = JsonConvert.DeserializeObject <dynamic>(ocoRes); var OcoOrder = new Ordem { DataCadastro = DateTime.UtcNow, Quantidade = SaldoQuantidade, Chamada_Id = ordem.Chamada_Id, Usuario_Id = user.Id, OrdemStatus_Id = 3, TipoOrdem_Id = 2, BinanceStatus_Id = 1, StopOrder_ID = StopOrderID, LimitOrder_ID = LimitOrderID, OcoOrderListId = (string)ocoObj.listClientOrderId, MainOrderID = ordem.Id }; _OrdemRepo.Add(OcoOrder); var resOco = ocoReturn.Content.ReadAsStringAsync().Result; Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (Ordem OCO Criada sucesso) OcoOrderListID => " + OcoOrder.OcoOrderListId); } else { var BinanceerrorObj = Helper.GetBinanceErrorObj(ocoReturn); Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (Erro ao Criar Ordem Oco) MainOrderID => " + ordem.Id + " => code => " + BinanceerrorObj.code + " => msg => " + BinanceerrorObj.msg + "/" + BinanceerrorObj.motivo); } } } #endregion #region VendaMercado else if (ordem != null && ordem.TipoOrdem_Id == 3) { var mainorder = _OrdemRepo.GetById((int)ordem.MainOrderID); mainorder.PrecoVendaMercado = (decimal)ws_Payload.L; mainorder.OrdemStatus_Id = 2; _OrdemRepo.Update(mainorder); } #endregion #region Order Oco else { //var OcoOrderId = (string)ws_Payload.c; ordem = _OrdemRepo.OcoOrderByBinanceOrderID(ordemID); if (ordem != null) { Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (Ordem OCO Executada) Stop_Or_Limit_ID => " + ordemID); var valorExecutado = ws_Payload.p; ordem.BinanceStatus_Id = 3; //status da order main tem que ser igual status da ultima ordem filha var mainOrder = _OrdemRepo.GetWith_Chamada_and_Symbol((int)ordem.MainOrderID); mainOrder.DataExecucao = DateTime.UtcNow; using (var _EdicaoAceitaRepo = new EdicaoAceitaRepository()) { var EdicaoAceita = _EdicaoAceitaRepo.AceitouEdicao(user.Id, mainOrder.Chamada_Id); if (EdicaoAceita == null) { if (valorExecutado >= ordem.Chamada.PrecoGain) { ordem.OrdemStatus_Id = 5; mainOrder.OrdemStatus_Id = 5; _OrdemRepo.Update(mainOrder); _OrdemRepo.Update(ordem); signalContext.Clients.User(user.Id.ToString()).GainRealizado(mainOrder); OneSignalApi.NotificarUsuario(user, mainOrder.Chamada.Symbol.symbol, NotificationType.Gain); } else if (valorExecutado <= ordem.Chamada.PrecoLoss) { ordem.OrdemStatus_Id = 6; mainOrder.OrdemStatus_Id = 6; _OrdemRepo.Update(mainOrder); _OrdemRepo.Update(ordem); signalContext.Clients.User(user.Id.ToString()).LossRealizado(mainOrder); OneSignalApi.NotificarUsuario(user, mainOrder.Chamada.Symbol.symbol, NotificationType.Loss); } } else { if (valorExecutado >= EdicaoAceita.ChamadaEditada.NewGain) { ordem.OrdemStatus_Id = 5; mainOrder.OrdemStatus_Id = 5; _OrdemRepo.Update(mainOrder); _OrdemRepo.Update(ordem); signalContext.Clients.User(user.Id.ToString()).GainRealizado(mainOrder); OneSignalApi.NotificarUsuario(user, mainOrder.Chamada.Symbol.symbol, NotificationType.Gain); } else if (valorExecutado <= EdicaoAceita.ChamadaEditada.NewLoss) { ordem.OrdemStatus_Id = 6; mainOrder.OrdemStatus_Id = 6; _OrdemRepo.Update(mainOrder); _OrdemRepo.Update(ordem); signalContext.Clients.User(user.Id.ToString()).LossRealizado(mainOrder); OneSignalApi.NotificarUsuario(user, mainOrder.Chamada.Symbol.symbol, NotificationType.Loss); } } } signalContext.Clients.User(user.Id.ToString()).RemoverEdicao(ordem.Chamada_Id); } } #endregion } //quando a ordem é quebrada em varios valores else if ((string)ws_Payload.x == "TRADE" && (string)ws_Payload.X == "PARTIALLY_FILLED") { string ordemID = (string)ws_Payload.c; var ordem = _OrdemRepo.EntradaByBinanceOrderID(ordemID); if (ordem != null && ordem.TipoOrdem_Id == 1) { using (var _OrderCommision = new OrdemComissionRepository()) { var Comission = new OrdemComission { Order_Id = ordem.Id, ComissionAmount = (decimal)ws_Payload.n, ComissionAsset = (string)ws_Payload.N, QtdExecutada = (decimal)ws_Payload.z, ValorExecutado = (decimal)ws_Payload.p }; _OrderCommision.Add(Comission); } } } //Ordem Expirada else if ((string)ws_Payload.x == "EXPIRED") { var orderId = (string)ws_Payload.c; var ordem = _OrdemRepo.EntradaByBinanceOrderID(orderId); if (ordem != null) { ordem.DataCancelamento = DateTime.UtcNow; ordem.BinanceStatus_Id = 7; ordem.OrdemStatus_Id = 7; _OrdemRepo.Update(ordem); signalContext.Clients.User(user.Id.ToString()).RejeitadaMercadoemFalta(ordem.Id); } } //Ordem Cancelada else if ((string)ws_Payload.x == "CANCELED") { var orderId = (string)ws_Payload.C; var mainOrder = _OrdemRepo.EntradaByBinanceOrderID(orderId); if (mainOrder != null && mainOrder.MotivoCancelamento_ID == null) { Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (Ordem Entrada Cancelada) OrderID => " + orderId); mainOrder.DataCancelamento = DateTime.UtcNow; mainOrder.BinanceStatus_Id = 4; mainOrder.OrdemStatus_Id = 4; mainOrder.MotivoCancelamento_ID = 1; _OrdemRepo.Update(mainOrder); signalContext.Clients.User(user.Id.ToString()).OrdemCancelada(mainOrder.MainOrderID == null ? mainOrder.Id : mainOrder.MainOrderID); } else { Logs.LogOrdem(user.Id + " (" + user.Email + ") => " + DateTime.UtcNow + " => Type (Ordem OCO Cancelada) Stop_Or_Limit_ID => " + orderId); var Ocoordem = _OrdemRepo.OcoOrderByBinanceOrderID(orderId); //venda a mercado if (Ocoordem != null && Ocoordem.MotivoCancelamento_ID == 2) { //A principio nao fazer nada } //Edicao Aceita else if (Ocoordem != null && Ocoordem.MotivoCancelamento_ID == 3) { //mainOrder = _OrdemRepo.GetById((int)Ocoordem.MainOrderID); //if (mainOrder != null && mainOrder.OrdemStatus_Id != 4) //{ // signalContext.Clients.User(user.Id.ToString()).OrdemCancelada(Ocoordem.MainOrderID == null ? mainOrder.Id : Ocoordem.MainOrderID); // mainOrder.OrdemStatus_Id = 4; // mainOrder.BinanceStatus_Id = 4; // mainOrder.DataCancelamento = DateTime.UtcNow; // _OrdemRepo.Update(mainOrder); //} } } } } //Atualiza saldo if ((string)ws_Payload.e == "outboundAccountPosition") { try { var listAssets = ws_Payload.B.ToObject <List <B> >(); var castedList = (List <B>)listAssets; var saldoBtc = castedList.Where(x => x.a == "BTC").FirstOrDefault().f; signalContext.Clients.User(user.Id.ToString()).AtualizarSaldo(saldoBtc.ToString("N8")); } catch (Exception) { } } } }; ws.OnError += (sender, e) => { Logs.LogConexao(user.Id + " (" + user.Nome + ") => OnError Event => " + DateTime.UtcNow + " Msg Erro => " + e.Message + " => inner exception => " + e.Exception.Message + " => stack trace => " + e.Exception.StackTrace); }; ws.OnClose += (sender, e) => { try { Logs.LogConexao(user.Id + " (" + user.Nome + ") => OnClose Event => " + DateTime.UtcNow + " code => " + e.Code + " motivo => " + e.Reason); var monitor = WSMonitor.Instancia; monitor.RemoveMonitor(User.Id); } catch { } }; ws.Connect(); } } }
public HttpResponseMessage aceitar([FromBody] AceitarEdicaoViewModel model) { try { if (model == null) { return(Request.CreateResponse(HttpStatusCode.NotAcceptable, "Campos Inválidos", "text/plain")); } if (ModelState.IsValid) { var userId = int.Parse(Helper.GetJWTPayloadValue(Request, "id")); var chamadaEditada = _ChamadaEditadaRepo.GetById(model.EdicaoId); var user = _UserRepo.GetById(userId); var ordem = _OrdemRepo.GetOcoOrder(userId, model.ChamadaId); ordem.MotivoCancelamento_ID = 3; _OrdemRepo.Update(ordem); //caso tenha cancelado e dado erro pra criar outra oco if (ordem.OrdemStatus_Id == 4 && ordem.BinanceStatus_Id == 4 && ordem.MotivoCancelamento_ID == 3) { string LimitOrderID, StopOrderID; do { LimitOrderID = Helper.GenerateRandomOcoOrderID(10); } while (_OrdemRepo.IsValidOrderID(LimitOrderID)); do { StopOrderID = Helper.GenerateRandomOcoOrderID(10); } while (_OrdemRepo.IsValidOrderID(StopOrderID)); var limitLoss = Helper.OcoStopLimitWithPercent(ordem.Chamada.Symbol_id, chamadaEditada.NewLoss, 0.5m); //cria uma nova ordem var ocoReturn = BinanceRestApi.SendSaidaOco(user.BinanceAPIKey, user.BinanceAPISecret, ordem.Chamada.Symbol.symbol, ordem.Quantidade, chamadaEditada.NewGain, chamadaEditada.NewLoss, limitLoss, LimitOrderID, StopOrderID); if (ocoReturn.IsSuccessStatusCode) { var edicaoAceita = new EdicaoAceita { Usuario_Id = userId, TipoEdicao_ID = 1, DataCadastro = DateTime.UtcNow, ChamadaEditada_ID = model.EdicaoId, Chamada_ID = model.ChamadaId }; _EdicaoAceitaRepo.Add(edicaoAceita); var ocoRes = ocoReturn.Content.ReadAsStringAsync().Result; var ocoObj = JsonConvert.DeserializeObject <dynamic>(ocoRes); var OcoOrder = new Ordem { DataCadastro = DateTime.UtcNow, DataExecucao = null, Quantidade = ordem.Quantidade, Chamada_Id = ordem.Chamada_Id, Usuario_Id = user.Id, OrdemStatus_Id = 3, TipoOrdem_Id = 2, BinanceStatus_Id = 1, StopOrder_ID = StopOrderID, LimitOrder_ID = LimitOrderID, OcoOrderListId = (string)ocoObj.listClientOrderId, MainOrderID = ordem.MainOrderID }; _OrdemRepo.Add(OcoOrder); var retunrobj = new { PrecoEntrada = ordem.Chamada.PrecoEntrada, NewGain = chamadaEditada.NewGain, NewLoss = chamadaEditada.NewLoss, chamadaId = chamadaEditada.Chamada_Id }; Logs.LogOrdem(user.Id + " (" + user.Email + ") => Type (Criar Ordem Editada Sucesso) MainOrderID => " + OcoOrder.MainOrderID); return(Request.CreateResponse(HttpStatusCode.OK, retunrobj)); } else { var BinanceErrorObj = Helper.GetBinanceErrorObj(ocoReturn); Logs.LogOrdem(user.Id + " (" + user.Email + ") => Type (Erro ao Criar Ordem Editada) OcoOrderListID => " + ordem.OcoOrderListId + " code => " + BinanceErrorObj.code + " motivo => " + BinanceErrorObj.msg); return(Request.CreateResponse(HttpStatusCode.BadRequest, BinanceErrorObj)); } } var res = BinanceRestApi.CancelarOco(user.BinanceAPIKey, user.BinanceAPISecret, ordem.Chamada.Symbol.symbol, ordem.OcoOrderListId); if (res.IsSuccessStatusCode) { ordem.OrdemStatus_Id = 4; ordem.BinanceStatus_Id = 4; ordem.DataCancelamento = DateTime.UtcNow; _OrdemRepo.Update(ordem); string LimitOrderID, StopOrderID; do { LimitOrderID = Helper.GenerateRandomOcoOrderID(10); } while (_OrdemRepo.IsValidOrderID(LimitOrderID)); do { StopOrderID = Helper.GenerateRandomOcoOrderID(10); } while (_OrdemRepo.IsValidOrderID(StopOrderID)); var limitLoss = Helper.OcoStopLimitWithPercent(ordem.Chamada.Symbol_id, chamadaEditada.NewLoss, 0.5m); //cria uma nova ordem var ocoReturn = BinanceRestApi.SendSaidaOco(user.BinanceAPIKey, user.BinanceAPISecret, ordem.Chamada.Symbol.symbol, ordem.Quantidade, chamadaEditada.NewGain, chamadaEditada.NewLoss, limitLoss, LimitOrderID, StopOrderID); if (ocoReturn.IsSuccessStatusCode) { var edicaoAceita = new EdicaoAceita { Usuario_Id = userId, TipoEdicao_ID = 1, DataCadastro = DateTime.UtcNow, ChamadaEditada_ID = model.EdicaoId, Chamada_ID = model.ChamadaId }; _EdicaoAceitaRepo.Add(edicaoAceita); var ocoRes = ocoReturn.Content.ReadAsStringAsync().Result; var ocoObj = JsonConvert.DeserializeObject <dynamic>(ocoRes); var OcoOrder = new Ordem { DataCadastro = DateTime.UtcNow, DataExecucao = null, Quantidade = ordem.Quantidade, Chamada_Id = ordem.Chamada_Id, Usuario_Id = user.Id, OrdemStatus_Id = 3, TipoOrdem_Id = 2, BinanceStatus_Id = 1, StopOrder_ID = StopOrderID, LimitOrder_ID = LimitOrderID, OcoOrderListId = (string)ocoObj.listClientOrderId, MainOrderID = ordem.MainOrderID }; _OrdemRepo.Add(OcoOrder); var retunrobj = new { PrecoEntrada = ordem.Chamada.PrecoEntrada, NewGain = chamadaEditada.NewGain, NewLoss = chamadaEditada.NewLoss, chamadaId = chamadaEditada.Chamada_Id }; Logs.LogOrdem(user.Id + " (" + user.Email + ") => Type (Criar Ordem Editada Sucesso) => OrderId => " + OcoOrder.Id + " => MainOrderID => " + OcoOrder.MainOrderID); return(Request.CreateResponse(HttpStatusCode.OK, retunrobj)); } else { var BinanceErrorObj = Helper.GetBinanceErrorObj(ocoReturn); Logs.LogOrdem(user.Id + " (" + user.Email + ") => Type (Erro ao Criar Ordem Editada) OcoOrderListID => " + ordem.OcoOrderListId + " code => " + BinanceErrorObj.code + " motivo => " + BinanceErrorObj.msg); return(Request.CreateResponse(HttpStatusCode.BadRequest, BinanceErrorObj)); } } else { var BinanceErrorObj = Helper.GetBinanceErrorObj(res); Logs.LogOrdem(user.Id + " (" + user.Email + ") => Type (Erro ao Cancelar Ordem Para Aceitar Edição) OcoOrderListID => " + ordem.OcoOrderListId + " code => " + BinanceErrorObj.code + " motivo => " + BinanceErrorObj.msg); return(Request.CreateResponse(HttpStatusCode.BadRequest, BinanceErrorObj)); } } var modelstateError = ModelStateErrors.DisplayModelStateError(ModelState); return(Request.CreateResponse(HttpStatusCode.NotAcceptable, modelstateError, "text/plain")); } catch (Exception ex) { return(Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message)); } }