PageRenderTime 69ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Sources/Algo/Storages/TraderStorageMonitor.cs

#
C# | 339 lines | 213 code | 49 blank | 77 comment | 18 complexity | 04ecb8bcc13013b6c5ef331c95dbc860 MD5 | raw file
Possible License(s): GPL-3.0
  1. //TraderStorageMonitor.cs
  2. //Copyright (c) 2013 StockSharp LLC, all rights reserved.
  3. //This code module is part of StockSharp library.
  4. //This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
  5. //See the file License.txt for the license details.
  6. //More info on: http://stocksharp.com
  7. namespace StockSharp.Algo.Storages
  8. {
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Threading;
  12. using Ecng.Collections;
  13. using Ecng.Common;
  14. using StockSharp.BusinessEntities;
  15. /// <summary>
  16. /// Специальный класс, сохраняющий данные из шлюзов <see cref="Traders"/> во внешнее хранилище.
  17. /// </summary>
  18. public class TraderStorageMonitor : Disposable
  19. {
  20. private sealed class TraderList : BaseList<ITrader>
  21. {
  22. private readonly TraderStorageMonitor _monitor;
  23. public TraderList(TraderStorageMonitor monitor)
  24. {
  25. if (monitor == null)
  26. throw new ArgumentNullException("monitor");
  27. _monitor = monitor;
  28. }
  29. protected override bool OnAdding(ITrader item)
  30. {
  31. item.NewSecurities += OnNewSecurities;
  32. item.SecuritiesChanged += OnSecuritiesChanged;
  33. item.NewTrades += OnNewTrades;
  34. item.NewMyTrades += OnNewMyTrades;
  35. item.NewOrders += OnNewOrders;
  36. item.OrdersChanged += OnOrdersChanged;
  37. item.OrdersRegisterFailed += OnOrdersRegisterFailed;
  38. item.OrdersCancelFailed += OnOrdersCancelFailed;
  39. item.NewStopOrders += OnNewOrders;
  40. item.StopOrdersChanged += OnOrdersChanged;
  41. item.StopOrdersRegisterFailed += OnOrdersRegisterFailed;
  42. item.StopOrdersCancelFailed += OnOrdersCancelFailed;
  43. item.MarketDepthsChanged += OnMarketDepthsChanged;
  44. item.NewPortfolios += OnNewPortfolios;
  45. item.PortfoliosChanged += OnPortfoliosChanged;
  46. item.PositionsChanged += OnPositionsChanged;
  47. return base.OnAdding(item);
  48. }
  49. protected override bool OnRemoving(ITrader item)
  50. {
  51. item.NewSecurities -= OnNewSecurities;
  52. item.SecuritiesChanged -= OnSecuritiesChanged;
  53. item.NewTrades -= OnNewTrades;
  54. item.NewMyTrades -= OnNewMyTrades;
  55. item.NewOrders -= OnNewOrders;
  56. item.OrdersChanged -= OnOrdersChanged;
  57. item.OrdersRegisterFailed -= OnOrdersRegisterFailed;
  58. item.OrdersCancelFailed -= OnOrdersCancelFailed;
  59. item.NewStopOrders -= OnNewOrders;
  60. item.StopOrdersChanged -= OnOrdersChanged;
  61. item.StopOrdersRegisterFailed -= OnOrdersRegisterFailed;
  62. item.StopOrdersCancelFailed -= OnOrdersCancelFailed;
  63. item.MarketDepthsChanged -= OnMarketDepthsChanged;
  64. item.NewPortfolios -= OnNewPortfolios;
  65. item.PortfoliosChanged -= OnPortfoliosChanged;
  66. item.PositionsChanged -= OnPositionsChanged;
  67. return base.OnRemoving(item);
  68. }
  69. private void OnPositionsChanged(IEnumerable<Position> positions)
  70. {
  71. if (CanSave(TraderStorageFilters.PositionChanged))
  72. positions.ForEach(_monitor.SavePosition);
  73. }
  74. private void OnPortfoliosChanged(IEnumerable<Portfolio> portfolios)
  75. {
  76. if (CanSave(TraderStorageFilters.PortfolioChanged))
  77. portfolios.ForEach(_monitor.SavePortfolio);
  78. }
  79. private void OnNewPortfolios(IEnumerable<Portfolio> portfolios)
  80. {
  81. if (CanSave(TraderStorageFilters.NewPortfolio))
  82. portfolios.ForEach(_monitor.SavePortfolio);
  83. }
  84. private void OnMarketDepthsChanged(IEnumerable<MarketDepth> depths)
  85. {
  86. if (CanSave(TraderStorageFilters.DepthsChanged))
  87. depths.ForEach(_monitor.SaveQuotes);
  88. }
  89. private void OnOrdersChanged(IEnumerable<Order> orders)
  90. {
  91. if (CanSave(TraderStorageFilters.OrderChanged))
  92. orders.ForEach(_monitor.SaveOrder);
  93. }
  94. private void OnOrdersRegisterFailed(IEnumerable<OrderFail> fails)
  95. {
  96. if (CanSave(TraderStorageFilters.RegisterOrderFailed))
  97. fails.ForEach(_monitor.SaveRegisterOrderFail);
  98. }
  99. private void OnOrdersCancelFailed(IEnumerable<OrderFail> fails)
  100. {
  101. if (CanSave(TraderStorageFilters.RegisterCancelFailed))
  102. fails.ForEach(_monitor.SaveCancelOrderFail);
  103. }
  104. private void OnNewOrders(IEnumerable<Order> orders)
  105. {
  106. if (CanSave(TraderStorageFilters.NewOrder))
  107. orders.ForEach(_monitor.SaveOrder);
  108. }
  109. private void OnNewTrades(IEnumerable<Trade> trades)
  110. {
  111. if (CanSave(TraderStorageFilters.NewTrade))
  112. trades.ForEach(_monitor.SaveTrade);
  113. }
  114. private void OnSecuritiesChanged(IEnumerable<Security> securities)
  115. {
  116. if (CanSave(TraderStorageFilters.SecurityChanged))
  117. securities.ForEach(_monitor.SaveSecurity);
  118. }
  119. private void OnNewSecurities(IEnumerable<Security> securities)
  120. {
  121. if (CanSave(TraderStorageFilters.NewSecurity))
  122. securities.ForEach(_monitor.SaveSecurity);
  123. }
  124. private void OnNewMyTrades(IEnumerable<MyTrade> trades)
  125. {
  126. if (CanSave(TraderStorageFilters.NewMyTrade))
  127. trades.ForEach(_monitor.SaveMyTrade);
  128. }
  129. private bool CanSave(TraderStorageFilters filter)
  130. {
  131. return _monitor.Filter.Contains(filter);
  132. }
  133. }
  134. private readonly MarketDataBuffer<MarketDepth> _depthBuffer = new MarketDataBuffer<MarketDepth>();
  135. private readonly MarketDataBuffer<Trade> _tradeBuffer = new MarketDataBuffer<Trade>();
  136. private DateTime _prevMarketDepthTime;
  137. private readonly Timer _timer;
  138. /// <summary>
  139. /// Создать <see cref="TraderStorageMonitor"/>.
  140. /// </summary>
  141. /// <param name="storageRegistry">Интерфейс, описывающий внешнее хранилище.</param>
  142. public TraderStorageMonitor(IStorageRegistry storageRegistry)
  143. {
  144. if (storageRegistry == null)
  145. throw new ArgumentNullException("storageRegistry");
  146. StorageRegistry = storageRegistry;
  147. Filter =
  148. TraderStorageFilters.NewSecurity |
  149. TraderStorageFilters.SecurityChanged |
  150. TraderStorageFilters.NewPortfolio |
  151. TraderStorageFilters.PortfolioChanged |
  152. TraderStorageFilters.PositionChanged |
  153. TraderStorageFilters.NewTrade |
  154. TraderStorageFilters.NewMyTrade |
  155. TraderStorageFilters.DepthsChanged |
  156. TraderStorageFilters.NewOrder |
  157. TraderStorageFilters.OrderChanged;
  158. Traders = new TraderList(this);
  159. _timer = ThreadingHelper.Timer(() =>
  160. {
  161. while (!IsDisposed)
  162. {
  163. _depthBuffer.Get().ForEach(p => StorageRegistry.GetMarketDepthStorage(p.Key).Save(p.Value));
  164. _tradeBuffer.Get().ForEach(p => StorageRegistry.GetTradeStorage(p.Key).Save(p.Value));
  165. TimeSpan.FromSeconds(1).Sleep();
  166. }
  167. }).Interval(TimeSpan.FromSeconds(1));
  168. }
  169. /// <summary>
  170. /// Интерфейс, описывающий внешнее хранилище.
  171. /// </summary>
  172. public IStorageRegistry StorageRegistry { get; private set; }
  173. /// <summary>
  174. /// Шлюзы, данные которых необходимо сохранять.
  175. /// </summary>
  176. public ICollection<ITrader> Traders { get; private set; }
  177. /// <summary>
  178. /// Приостановлен ли процесс сохранения поступающих данных.
  179. /// </summary>
  180. public bool IsSuspended { get; set; }
  181. /// <summary>
  182. /// Фильтры данных, которые необходимо сохранять.
  183. /// По-умолчанию, выбраны все фильтры.
  184. /// Для установления нового фильтра необходимо использовать следующий вид записи:
  185. /// <code>
  186. /// // сохранять только новые инструменты, заявки и мои сделки
  187. /// Mode = TraderStorageFilters.NewSecurity | TraderStorageFilters.NewOrder | TraderStorageFilters.NewMyTrade;
  188. /// </code>
  189. /// </summary>
  190. public TraderStorageFilters Filter { get; set; }
  191. /// <summary>
  192. /// Дискретный шаг во времени, определяющий, как часто надо сохранять изменения в стакане.
  193. /// По умолчанию значение равно <see cref="TimeSpan.Zero"/>, что означает непрерывное сохранение изменений в стакане.
  194. /// </summary>
  195. public TimeSpan MarketDepthTimeStep { get; set; }
  196. /// <summary>
  197. /// Принудительно очистить кэш.
  198. /// </summary>
  199. public void Flush()
  200. {
  201. _depthBuffer.Get().ForEach(p => StorageRegistry.GetMarketDepthStorage(p.Key).Save(p.Value));
  202. _tradeBuffer.Get().ForEach(p => StorageRegistry.GetTradeStorage(p.Key).Save(p.Value));
  203. }
  204. /// <summary>
  205. /// Сохранить информацию по инструменту.
  206. /// </summary>
  207. /// <param name="security">Инструмент, информацию которого необходимо сохранить.</param>
  208. protected virtual void SaveSecurity(Security security)
  209. {
  210. StorageRegistry.Securities.Save(security);
  211. }
  212. /// <summary>
  213. /// Сохранить информацию по заявке.
  214. /// </summary>
  215. /// <param name="order">Заявка, информацию которой необходимо сохранить.</param>
  216. protected virtual void SaveOrder(Order order)
  217. {
  218. StorageRegistry.Orders.Save(order);
  219. }
  220. /// <summary>
  221. /// Сохранить информацию об ошибке регистрации заявки.
  222. /// </summary>
  223. /// <param name="fail">Описание ошибки, которая произошла при регистрации заявки.</param>
  224. protected virtual void SaveRegisterOrderFail(OrderFail fail)
  225. {
  226. StorageRegistry.OrderFails.Save(fail);
  227. }
  228. /// <summary>
  229. /// Сохранить информацию об ошибке снятия заявки.
  230. /// </summary>
  231. /// <param name="fail">Описание ошибки, которая произошла при снятии заявки.</param>
  232. protected virtual void SaveCancelOrderFail(OrderFail fail)
  233. {
  234. StorageRegistry.OrderFails.Save(fail);
  235. }
  236. /// <summary>
  237. /// Сохранить информацию по моей сделке.
  238. /// </summary>
  239. /// <param name="trade">Моя сделка, информацию которой необходимо сохранить.</param>
  240. protected virtual void SaveMyTrade(MyTrade trade)
  241. {
  242. StorageRegistry.MyTrades.Save(trade);
  243. }
  244. /// <summary>
  245. /// Сохранить информацию по сделке.
  246. /// </summary>
  247. /// <param name="trade">Сделка, информацию которой необходимо сохранить.</param>
  248. protected virtual void SaveTrade(Trade trade)
  249. {
  250. _tradeBuffer.Add(trade.Security, trade);
  251. }
  252. /// <summary>
  253. /// Сохранить информацию по стакану.
  254. /// </summary>
  255. /// <param name="depth">Стакан, информацию которого необходимо сохранить.</param>
  256. protected virtual void SaveQuotes(MarketDepth depth)
  257. {
  258. if ((DateTime.Now - _prevMarketDepthTime) < MarketDepthTimeStep)
  259. return;
  260. _prevMarketDepthTime = DateTime.Now;
  261. _depthBuffer.Add(depth.Security, depth.Clone());
  262. }
  263. /// <summary>
  264. /// Сохранить информацию по портфелю.
  265. /// </summary>
  266. /// <param name="portfolio">Портфель, информацию которого необходимо сохранить.</param>
  267. protected virtual void SavePortfolio(Portfolio portfolio)
  268. {
  269. StorageRegistry.Portfolios.Save(portfolio);
  270. }
  271. /// <summary>
  272. /// Сохранить информацию по позиции.
  273. /// </summary>
  274. /// <param name="position">Позиция, информацию которой необходимо сохранить.</param>
  275. protected virtual void SavePosition(Position position)
  276. {
  277. StorageRegistry.Positions.Save(position);
  278. }
  279. /// <summary>
  280. /// Освободить занятые ресурсы.
  281. /// </summary>
  282. protected override void DisposeManaged()
  283. {
  284. _timer.Dispose();
  285. Traders.Clear();
  286. Flush();
  287. base.DisposeManaged();
  288. }
  289. }
  290. }