/// <summary> /// Funkcja zamieniająca komunikat odebrany z socketa (klasy bazowej FixmlMsg) /// na konkretną klasę pochodną FixmlMsg - odpowiednią dla typu danego komunikatu. /// Obecnie przystosowane tylko dla komunikatów nadsyłanych w kanale asynchronicznym /// (raczej tylko tam ma to sens, normalnie wiemy jakiego komunikatu się spodziewać). /// </summary> /// <param name="msg">Obiekt klasy bazowej FixmlMsg</param> /// <returns>Obiekt konkretnej klasy pochodnej FixmlMsg, zależnej od typu komunikatu. /// Jeśli trafi na nieznany komunikat, zwraca ten sam obiekt bazowy FixmlMsg. /// </returns> public static FixmlMsg GetParsedMsg(FixmlMsg msg) { if (msg.GetType() != typeof(FixmlMsg)) { throw new ArgumentException("Base 'FixmlMsg' class object required", "msg"); } switch (msg.Xml.Name) { case AppMessageReportMsg.MsgName: return(new AppMessageReportMsg(msg)); case ExecutionReportMsg.MsgName: return(new ExecutionReportMsg(msg)); case MarketDataIncRefreshMsg.MsgName: return(new MarketDataIncRefreshMsg(msg)); case TradingSessionStatusMsg.MsgName: return(new TradingSessionStatusMsg(msg)); case NewsMsg.MsgName: return(new NewsMsg(msg)); case StatementMsg.MsgName: return(new StatementMsg(msg)); case UserResponseMsg.MsgName: return(new UserResponseMsg(msg)); case "Heartbeat": return(msg); // <- dla tego szkoda oddzielnej klasy ;-) default: string txt = string.Format("Unexpected async message '{0}'", msg.Xml.Name); MyUtil.PrintWarning(txt); if (!FixmlMsg.DebugOriginalXml.Enabled && !FixmlMsg.DebugFormattedXml.Enabled) { Trace.WriteLine(string.Format("'{0}'", MyUtil.FormattedXml(msg.Xml.OwnerDocument))); } return(msg); } }
// Konstruktor używany wewnętrznie dla komunikatów przychodzących - // "opakowywuje" odebrany komunikat w inną, bardziej precyzyjną klasę pochodną. protected FixmlMsg(FixmlMsg msg) { Debug.WriteLineIf(DebugInternals.Enabled, string.Format("new {0} from FixmlMsg", GetType().Name), DebugCategory); xmlDoc = msg.xmlDoc; ParseXmlMessage(null); Debug.WriteLineIf(DebugParsedMessage.Enabled, this.ToString(), DebugRecvCategory); Debug.WriteLineIf(DebugInternals.Enabled, string.Format("new {0} ok", GetType().Name), DebugCategory); }
public ExecutionReportMsg(FixmlMsg m) : base(m) { }
public TradingSessionStatusMsg(FixmlMsg msg) : base(msg) { }
public StatementMsg(FixmlMsg m) : base(m) { }
public NewsMsg(FixmlMsg m) : base(m) { }
/// <summary> /// Funkcja zamieniająca komunikat odebrany z socketa (klasy bazowej FixmlMsg) /// na konkretną klasę pochodną FixmlMsg - odpowiednią dla typu danego komunikatu. /// Obecnie przystosowane tylko dla komunikatów nadsyłanych w kanale asynchronicznym /// (raczej tylko tam ma to sens, normalnie wiemy jakiego komunikatu się spodziewać). /// </summary> /// <param name="msg">Obiekt klasy bazowej FixmlMsg</param> /// <returns>Obiekt konkretnej klasy pochodnej FixmlMsg, zależnej od typu komunikatu. /// Jeśli trafi na nieznany komunikat, zwraca ten sam obiekt bazowy FixmlMsg. /// </returns> public static FixmlMsg GetParsedMsg(FixmlMsg msg) { if (msg.GetType() != typeof(FixmlMsg)) throw new ArgumentException("Base 'FixmlMsg' class object required", "msg"); switch (msg.Xml.Name) { case AppMessageReportMsg.MsgName: return new AppMessageReportMsg(msg); case ExecutionReportMsg.MsgName: return new ExecutionReportMsg(msg); case MarketDataIncRefreshMsg.MsgName: return new MarketDataIncRefreshMsg(msg); case TradingSessionStatusMsg.MsgName: return new TradingSessionStatusMsg(msg); case NewsMsg.MsgName: return new NewsMsg(msg); case StatementMsg.MsgName: return new StatementMsg(msg); case UserResponseMsg.MsgName: return new UserResponseMsg(msg); case "Heartbeat": return msg; // <- dla tego szkoda oddzielnej klasy ;-) default: string txt = string.Format("Unexpected async message '{0}'", msg.Xml.Name); MyUtil.PrintWarning(txt); if (!FixmlMsg.DebugOriginalXml.Enabled && !FixmlMsg.DebugFormattedXml.Enabled) Trace.WriteLine(string.Format("'{0}'", MyUtil.FormattedXml(msg.Xml.OwnerDocument))); return msg; } }
public FixmlErrorMsgException(string str, FixmlMsg msg) : base(str) { this.msg = msg; }
/// <summary> /// Bardziej zaawansowany przykład użycia "NolClient": zalogowanie dopiero na żądanie, /// bez uruchamiania wątku odbierającego komunikaty asynchroniczne (można go obsłużyć samemu). /// Samodzielne przygotowanie, wysyłka i odbiór przykładowego message'a. /// </summary> public void Execute() { using (var nol = new NolClient(false, false)) { // zalogowanie użytkownika Console.WriteLine("\nPress any key... to log in [Esc - cancel]\n"); if (Console.ReadKey(true).Key == ConsoleKey.Escape) return; nol.Login(); // otwarcie kanału asynchronicznego // (na razie nic tu z niego nie odbieramy, bo do tego przydałby się oddzielny wątek) Console.WriteLine("\nPress any key... to open async socket [Esc - skip]\n"); Socket asyncSocket = null; if (Console.ReadKey(true).Key != ConsoleKey.Escape) asyncSocket = NolClient.GetAsyncSocket(); // wysyłka przykładowego komunikatu // (można skorzystać z gotowych klas zdefiniowanych w pjank.BossaAPI.Fixml, // ale można też spreparować coś zupełnie własnego w oparciu o klasę CustomMsg) Console.WriteLine("\nPress any key... to send a custom message [Esc - cancel]\n"); if (Console.ReadKey(true).Key == ConsoleKey.Escape) return; var tmp = FixmlMsg.DebugOriginalXml.Enabled; try { FixmlMsg.DebugOriginalXml.Enabled = true; // otwarcie nowego połączenia (kanał synchroniczny za każdym razem nowy!) using (var syncSocket = NolClient.GetSyncSocket()) { // przygotowanie komunikatu var request = new UserRequestMsg() { Username = "******", Type = UserRequestType.GetStatus, }; // wysyłka komunikatu request.Send(syncSocket); // odbiór odpowiedzi Console.WriteLine("\nPress any key... to read the response\n"); Console.ReadKey(true); var response = new FixmlMsg(syncSocket); Trace.WriteLine("\nResponse XML:\n" + response.Xml.FormattedXml() + "\n"); // dokładniejsza analiza odpowiedzi (w klasie konkretnego rodzaju komunikatu) Console.WriteLine("Press any key... to parse the response message\n"); Console.ReadKey(true); UserResponseMsg parsedResponse = new UserResponseMsg(response); Trace.WriteLine(String.Format("\nResponse parsed:\n Status = {0}, StatusText = '{1}'\n", parsedResponse.Status, parsedResponse.StatusText)); } Console.WriteLine("\nPress any key... to send another custom message [Esc - cancel]\n"); if (Console.ReadKey(true).Key == ConsoleKey.Escape) return; // otwarcie nowego połączenia (kanał synchroniczny za każdym razem nowy!) using (var syncSocket = NolClient.GetSyncSocket()) { // tak można spreparować dowolny komunikat, również taki jeszcze nieistniejący ;-> var request = new CustomMsg("MyCustomRequest"); var xmlElement = request.AddElement("Test"); xmlElement.SetAttribute("attr1", "1"); xmlElement.SetAttribute("attr2", "2"); // wysyłka tak samodzielnie spreparowanego komunikatu request.Send(syncSocket); // odbiór odpowiedzi - tutaj powinniśmy otrzymać błąd... "BizMessageRejectException" // niestety aktualna wersja NOL3 zwraca nieprawidłowy XML, którego nie da się parsować Console.WriteLine("\nPress any key... to read the response\n"); Console.ReadKey(true); var response = new FixmlMsg(syncSocket); } } catch (Exception e) { MyUtil.PrintError(e); } FixmlMsg.DebugOriginalXml.Enabled = tmp; Console.ReadKey(true); if (asyncSocket != null) asyncSocket.Close(); } // tu następuje automatyczne wylogowanie }
public MarketDataIncRefreshMsg(FixmlMsg m) : base(m) { }
// procedura wątku z obsługą kanału asynchronicznego private void ThreadProc() { try { using (Socket socket = GetAsyncSocket()) { while (socket.Connected) { Debug.WriteLineIf(FixmlMsg.DebugInternals.Enabled, ""); FixmlMsg msg; // odbiór komunikatu, na razie w "bezimiennej" klasie bazowej FixmlMsg try { msg = new FixmlMsg(socket); } catch (ThreadAbortException) { throw; } catch (FixmlSocketException) { throw; } catch (Exception e) { e.PrintError(); continue; } // rozpoznanie typu komunikatu i przetworzenie na konkretną klasę pochodną z FixmlMsg try { msg = FixmlMsg.GetParsedMsg(msg); } catch (ThreadAbortException) { throw; } catch (Exception e) { e.PrintError(); } // wywołanie podpiętych metod obsługi danego komunikatu try { if (AsyncMessageEvent != null) AsyncMessageEvent(msg); if (msg is AppMessageReportMsg) if (AppReportMsgEvent != null) AppReportMsgEvent((AppMessageReportMsg)msg); if (msg is ExecutionReportMsg) if (ExecReportMsgEvent != null) ExecReportMsgEvent((ExecutionReportMsg)msg); if (msg is MarketDataIncRefreshMsg) if (MarketDataMsgEvent != null) MarketDataMsgEvent((MarketDataIncRefreshMsg)msg); if (msg is TradingSessionStatusMsg) if (SessionStatusMsgEvent != null) SessionStatusMsgEvent((TradingSessionStatusMsg)msg); if (msg is NewsMsg) if (NewsMsgEvent != null) NewsMsgEvent((NewsMsg)msg); if (msg is StatementMsg) if (StatementMsgEvent != null) StatementMsgEvent((StatementMsg)msg); if (msg is UserResponseMsg) if (UserResponseMsgEvent != null) UserResponseMsgEvent((UserResponseMsg)msg); } catch (ThreadAbortException) { throw; } catch (Exception e) { e.PrintError(); } } } } catch (ThreadAbortException) { Thread.ResetAbort(); } catch (Exception e) { e.PrintError(); } Debug.WriteLineIf(FixmlMsg.DebugInternals.Enabled, "NolClient.ThreadProc stop", FixmlMsg.DebugCategory); }
public UserResponseMsg(FixmlMsg m) : base(m) { }
public FixmlErrorMsgException(FixmlMsg msg) : this(msg.ToString(), msg) { }