├── .gitignore
├── App.xaml
├── App.xaml.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── QScalp
├── DataTypes.cs
├── Internals
│ ├── DateTimeHelper.cs
│ ├── Flags.cs
│ ├── Leb128.cs
│ ├── QshFile.cs
│ ├── StreamType.cs
│ └── ULeb128.cs
├── RawQuotes.cs
├── Reader
│ ├── IQshStream.cs
│ ├── QshReader.cs
│ └── V4
│ │ ├── AuxInfoStream.cs
│ │ ├── DataReader.cs
│ │ ├── DealsStream.cs
│ │ ├── MessagesStream.cs
│ │ ├── OrdLogStream.cs
│ │ ├── OwnOrdersStream.cs
│ │ ├── OwnTradesStream.cs
│ │ ├── QshReaderImpl.cs
│ │ ├── QshStream.cs
│ │ └── QuotesStream.cs
├── Security.cs
└── Writer
│ ├── AuxInfoStream.cs
│ ├── DataWriter.cs
│ ├── DealsStream.cs
│ ├── MessagesStream.cs
│ ├── OrdLogStream.cs
│ ├── OwnOrdersStream.cs
│ ├── OwnTradesStream.cs
│ ├── QshWriter.cs
│ └── QuotesStream.cs
├── Qsh2StockSharp.csproj
├── Qsh2StockSharp.sln
├── README.md
├── app.config
└── stocksharp.ico
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin
2 | /obj
3 | /*.user
4 | /*.suo
5 | *.suo
6 | /packages/
7 | /TestData/
8 | /.vs/
9 |
--------------------------------------------------------------------------------
/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/App.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace StockSharp.Qsh2StockSharp
2 | {
3 | public partial class App
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | QSH:
34 |
35 |
36 | S#:
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Board code:
59 |
60 |
61 | Security Code Masks:
62 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | Output format:
99 |
100 |
101 | Multi thread convertion
102 |
103 | OL -> Стакан
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace StockSharp.Qsh2StockSharp
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 |
11 | using DevExpress.Xpf.Core;
12 |
13 | using Ecng.Common;
14 | using Ecng.Collections;
15 | using Ecng.Serialization;
16 | using Ecng.Xaml;
17 |
18 | using MoreLinq;
19 |
20 | using QScalp;
21 | using QScalp.History;
22 | using QScalp.History.Reader;
23 |
24 | using StockSharp.Algo;
25 | using StockSharp.Algo.Storages;
26 | using StockSharp.BusinessEntities;
27 | using StockSharp.Localization;
28 | using StockSharp.Logging;
29 | using StockSharp.Messages;
30 | using StockSharp.Plaza;
31 | using StockSharp.Xaml;
32 |
33 | public partial class MainWindow
34 | {
35 | private class Settings
36 | {
37 | public string QshFolder { get; set; }
38 | public string StockSharpFolder { get; set; }
39 | public StorageFormats Format { get; set; }
40 | public string Board { get; set; }
41 | public string SecurityLike { get; set; }
42 | public bool MultiThread { get; set; }
43 | public bool OrderLog2OrderBook { get; set; }
44 | public int OrderBookMaxDepth { get; set; } = 5;
45 | public string TimeStampZone { get; set; }
46 | public string MarketDataZone { get; set; }
47 | }
48 |
49 | private readonly LogManager _logManager = new LogManager();
50 |
51 | private bool _isStarted;
52 |
53 | private DateTimeOffset _startConvertTime;
54 |
55 | private const string _settingsDir = "Settings";
56 |
57 | private static readonly string _settingsFile = Path.Combine(_settingsDir, "settings.xml");
58 | private static readonly string _convertedFilesFile = Path.Combine(_settingsDir, "converted_files.txt");
59 |
60 | private readonly HashSet _convertedFiles = new HashSet(StringComparer.InvariantCultureIgnoreCase);
61 | private readonly HashSet _convertedPerTaskPoolFiles = new HashSet(StringComparer.InvariantCultureIgnoreCase);
62 |
63 | public MainWindow()
64 | {
65 | InitializeComponent();
66 |
67 | Title = TypeHelper.ApplicationNameWithVersion;
68 |
69 | ApplicationThemeHelper.ApplicationThemeName = ThemeExtensions.DefaultTheme;
70 |
71 | Directory.CreateDirectory(_settingsDir);
72 |
73 | TimeStampZone.TimeZone = TimeZoneInfo.Utc;
74 | MarketDataZone.TimeZone = TimeHelper.Moscow;
75 |
76 | _logManager.Application.LogLevel = LogLevels.Verbose;
77 |
78 | _logManager.Listeners.Add(new GuiLogListener(LogControl));
79 | _logManager.Listeners.Add(new FileLogListener { LogDirectory = "Logs", SeparateByDates = SeparateByDateModes.FileName });
80 |
81 | Format.SetDataSource();
82 | Format.SetSelectedValue(StorageFormats.Binary);
83 |
84 | Board.Boards.AddRange(ExchangeBoard.EnumerateExchangeBoards().Where(b => b.Exchange == Exchange.Moex));
85 | Board.SelectedBoard = ExchangeBoard.Forts;
86 |
87 | try
88 | {
89 | if (File.Exists(_settingsFile))
90 | {
91 | var settings = new XmlSerializer().Deserialize(_settingsFile);
92 |
93 | QshFolder.Folder = settings.QshFolder;
94 | StockSharpFolder.Folder = settings.StockSharpFolder;
95 | Format.SetSelectedValue(settings.Format);
96 | SecurityLike.Text = settings.SecurityLike;
97 | MultiThread.IsChecked = settings.MultiThread;
98 | OrderLog2OrderBook.IsChecked = settings.OrderLog2OrderBook;
99 |
100 | Board.SelectedBoard =
101 | settings.Board.IsEmpty()
102 | ? ExchangeBoard.Forts
103 | : Board.Boards.FirstOrDefault(b => b.Code.CompareIgnoreCase(settings.Board)) ?? ExchangeBoard.Forts;
104 |
105 | if (!settings.TimeStampZone.IsEmpty())
106 | TimeStampZone.TimeZone = TimeZoneInfo.FindSystemTimeZoneById(settings.TimeStampZone);
107 |
108 | if (!settings.MarketDataZone.IsEmpty())
109 | MarketDataZone.TimeZone = TimeZoneInfo.FindSystemTimeZoneById(settings.MarketDataZone);
110 | }
111 |
112 | if (File.Exists(_convertedFilesFile))
113 | {
114 | _convertedFiles.AddRange(File.ReadAllLines(_convertedFilesFile));
115 | }
116 | }
117 | catch (Exception ex)
118 | {
119 | ex.LogError();
120 | }
121 | }
122 |
123 | protected override void OnClosed(EventArgs e)
124 | {
125 | SaveSettings();
126 | base.OnClosed(e);
127 | }
128 |
129 | private Settings SaveSettings()
130 | {
131 | var settings = new Settings
132 | {
133 | QshFolder = QshFolder.Folder,
134 | StockSharpFolder = StockSharpFolder.Folder,
135 | Format = Format.GetSelectedValue() ?? StorageFormats.Binary,
136 | SecurityLike = SecurityLike.Text,
137 | Board = Board.SelectedBoard?.Code,
138 | MultiThread = MultiThread.IsChecked == true,
139 | OrderLog2OrderBook = OrderLog2OrderBook.IsEnabled && OrderLog2OrderBook.IsChecked == true,
140 | TimeStampZone = TimeStampZone.TimeZone.Id,
141 | MarketDataZone = MarketDataZone.TimeZone.Id,
142 | };
143 |
144 | try
145 | {
146 | new XmlSerializer().Serialize(settings, _settingsFile);
147 | }
148 | catch (Exception ex)
149 | {
150 | ex.LogError();
151 | }
152 |
153 | return settings;
154 | }
155 |
156 | private void LockControls(bool isEnabled)
157 | {
158 | FoldersGrid.IsEnabled = StorageSettingsBox.IsEnabled = SecSettingsBox.IsEnabled = isEnabled;
159 | }
160 |
161 | private void Convert_OnClick(object sender, RoutedEventArgs e)
162 | {
163 | Convert.IsEnabled = false;
164 |
165 | if (_isStarted)
166 | {
167 | _logManager.Application.AddInfoLog("Остановка конвертации.");
168 | _isStarted = false;
169 | return;
170 | }
171 |
172 | LockControls(false);
173 |
174 | _logManager.Application.AddInfoLog("Запуск конвертации.");
175 | _isStarted = true;
176 |
177 | var settings = SaveSettings();
178 | var board = Board.SelectedBoard;
179 |
180 | var orderLog2OrderBookBuilders = settings.OrderLog2OrderBook ? new Dictionary() : null;
181 | var tz = TimeStampZone.TimeZone;
182 | var mz = MarketDataZone.TimeZone;
183 |
184 | Task.Factory.StartNew(() =>
185 | {
186 | var registry = new StorageRegistry();
187 | ((LocalMarketDataDrive)registry.DefaultDrive).Path = settings.StockSharpFolder;
188 |
189 | this.GuiAsync(() =>
190 | {
191 | Convert.Content = LocalizedStrings.Str2890;
192 | Convert.IsEnabled = true;
193 | });
194 |
195 | _startConvertTime = DateTimeOffset.Now;
196 |
197 | ConvertDirectory(settings.QshFolder, registry, settings.Format, board, settings.SecurityLike, settings.MultiThread, orderLog2OrderBookBuilders, settings.OrderBookMaxDepth, tz, mz);
198 | })
199 | .ContinueWith(t =>
200 | {
201 | Convert.Content = LocalizedStrings.Str2932;
202 | Convert.IsEnabled = true;
203 |
204 | LockControls(true);
205 |
206 | if (t.IsFaulted)
207 | {
208 | t.Exception.LogError();
209 |
210 | new MessageBoxBuilder()
211 | .Text("В процессе конвертации произошла ошибка. Ошибка записана в лог.")
212 | .Error()
213 | .Owner(this)
214 | .Show();
215 |
216 | return;
217 | }
218 |
219 | var text = "Конвертация {0} {1}.".Put(_isStarted ? "выполнена за" : "остановлена через",
220 | (DateTimeOffset.Now - _startConvertTime).ToString("g"));
221 |
222 | _logManager.Application.AddInfoLog(text);
223 |
224 | new MessageBoxBuilder()
225 | .Text(text)
226 | .Owner(this)
227 | .Show();
228 |
229 | _isStarted = false;
230 |
231 | }, TaskScheduler.FromCurrentSynchronizationContext());
232 | }
233 |
234 | private void ConvertDirectory(string path, IStorageRegistry registry, StorageFormats format, ExchangeBoard board, string securityLike, bool multithread, Dictionary orderLog2OrderBookBuilders, int orderBookMaxDepth, TimeZoneInfo tz, TimeZoneInfo mz)
235 | {
236 | if (!_isStarted)
237 | return;
238 |
239 | var files = Directory.GetFiles(path, "*.qsh");
240 |
241 | if (!multithread)
242 | files.ForEach(f => ConvertFile(f, registry, format, board, securityLike, orderLog2OrderBookBuilders, orderBookMaxDepth, tz, mz));
243 | else
244 | {
245 | Parallel.ForEach(files, file => ConvertFile(file, registry, format, board, securityLike, orderLog2OrderBookBuilders, orderBookMaxDepth, tz, mz));
246 | }
247 |
248 | //пишем имена сконвертированных в деректории файлов qsh, в файл
249 | File.AppendAllLines(_convertedFilesFile, _convertedPerTaskPoolFiles);
250 | _convertedPerTaskPoolFiles.Clear();
251 |
252 | Directory.GetDirectories(path).ForEach(d => ConvertDirectory(d, registry, format, board, securityLike, multithread, orderLog2OrderBookBuilders, orderBookMaxDepth, tz, mz));
253 | }
254 |
255 | private void TryFlushData(IStorageRegistry registry, SecurityId securityId, StorageFormats format, object arg, List messages, QshReader reader)
256 | where TMessage : Messages.Message
257 | {
258 | const int maxBufCount = 1000;
259 |
260 | if (messages.Count <= maxBufCount)
261 | return;
262 |
263 | _logManager.Application.AddDebugLog("Файл прочитан на {1}%.", messages.Count, (reader.FilePosition * 100) / reader.FileSize);
264 |
265 | registry.GetStorage(securityId, typeof(TMessage), arg, null, format).Save(messages);
266 | messages.Clear();
267 | }
268 |
269 | private void ConvertFile(string fileName, IStorageRegistry registry, StorageFormats format, ExchangeBoard board, string securityLike, Dictionary orderLog2OrderBookBuilders, int orderBookMaxDepth, TimeZoneInfo tz, TimeZoneInfo mz)
270 | {
271 | if (!_isStarted)
272 | return;
273 |
274 | var fileNameKey = format + "_" + fileName;
275 |
276 | if (_convertedFiles.Contains(fileNameKey))
277 | return;
278 |
279 | _logManager.Application.AddInfoLog("Начата конвертация файла {0}.", fileName);
280 |
281 | var securitiesStrings = securityLike.Split(",");
282 |
283 | var data = new Dictionary, List, List, List>>();
284 |
285 | DateTimeOffset ToLocalDto(DateTime dt) => dt.ApplyTimeZone(tz);
286 | DateTimeOffset ToServerDto(DateTime dt) => dt.ApplyTimeZone(mz);
287 |
288 | using (var qr = QshReader.Open(fileName))
289 | {
290 | var reader = qr;
291 |
292 | for (var i = 0; i < qr.StreamCount; i++)
293 | {
294 | var stream = (ISecurityStream)qr[i];
295 | var securityId = GetSecurityId(stream.Security, board.Code);
296 | var priceStep = (decimal)stream.Security.Step;
297 | var lastTransactionId = 0L;
298 | var builder = orderLog2OrderBookBuilders?.SafeAdd(securityId, key => new PlazaOrderLogMarketDepthBuilder(key));
299 |
300 | if (securitiesStrings.Length > 0)
301 | {
302 | var secCode = securityId.SecurityCode;
303 |
304 | var streamContainsSecurityFromMask = securitiesStrings.Any(mask =>
305 | {
306 | var isEndMulti = mask.EndsWith("*");
307 | var isStartMulti = mask.StartsWith("*");
308 |
309 | if (isStartMulti)
310 | mask = mask.Substring(1);
311 |
312 | if (isEndMulti)
313 | mask = mask.Substring(0, mask.Length - 1);
314 |
315 | if (isEndMulti)
316 | {
317 | if (isStartMulti)
318 | return secCode.ContainsIgnoreCase(mask);
319 | else
320 | return secCode.StartsWith(mask, StringComparison.InvariantCultureIgnoreCase);
321 | }
322 | else if (isStartMulti)
323 | return secCode.EndsWith(mask, StringComparison.InvariantCultureIgnoreCase);
324 | else
325 | return secCode.CompareIgnoreCase(mask);
326 | });
327 |
328 | if (!streamContainsSecurityFromMask)
329 | continue;
330 | }
331 |
332 | var secData = data.SafeAdd(securityId, key => Tuple.Create(new List(), new List(), new List(), new List()));
333 |
334 | switch (stream.Type)
335 | {
336 | case StreamType.Quotes:
337 | {
338 | ((IQuotesStream)stream).Handler += quotes =>
339 | {
340 | var bids = new List();
341 | var asks = new List();
342 |
343 | foreach (var q in quotes)
344 | {
345 | switch (q.Type)
346 | {
347 | //case QuoteType.Unknown:
348 | //case QuoteType.Free:
349 | //case QuoteType.Spread:
350 | // throw new ArgumentException(q.Type.ToString());
351 | case QuoteType.Ask:
352 | case QuoteType.BestAsk:
353 | asks.Add(new QuoteChange(priceStep * q.Price, q.Volume));
354 | break;
355 | case QuoteType.Bid:
356 | case QuoteType.BestBid:
357 | bids.Add(new QuoteChange(priceStep * q.Price, q.Volume));
358 | break;
359 | default:
360 | {
361 | continue;
362 | //throw new ArgumentException(q.Type.ToString());
363 | }
364 | }
365 | }
366 |
367 | var md = new QuoteChangeMessage
368 | {
369 | LocalTime = ToLocalDto(reader.CurrentDateTime),
370 | SecurityId = securityId,
371 | ServerTime = ToLocalDto(reader.CurrentDateTime),
372 | Bids = bids.ToArray(),
373 | Asks = asks.ToArray(),
374 | };
375 |
376 | //if (md.Verify())
377 | //{
378 | secData.Item1.Add(md);
379 |
380 | TryFlushData(registry, securityId, format, null, secData.Item1, reader);
381 |
382 | //}
383 | //else
384 | // _logManager.Application.AddErrorLog("Стакан для {0} в момент {1} не прошел валидацию. Лучший бид {2}, Лучший офер {3}.", security, qr.CurrentDateTime, md.BestBid, md.BestAsk);
385 | };
386 | break;
387 | }
388 | case StreamType.Deals:
389 | {
390 | ((IDealsStream)stream).Handler += deal =>
391 | {
392 | secData.Item2.Add(new ExecutionMessage
393 | {
394 | LocalTime = ToLocalDto(reader.CurrentDateTime),
395 | HasTradeInfo = true,
396 | ExecutionType = ExecutionTypes.Tick,
397 | SecurityId = securityId,
398 | OpenInterest = deal.OI == 0 ? (long?)null : deal.OI,
399 | ServerTime = ToServerDto(deal.DateTime),
400 | TradeVolume = deal.Volume,
401 | TradeId = deal.Id == 0 ? (long?)null : deal.Id,
402 | TradePrice = deal.Price * priceStep,
403 | OriginSide =
404 | deal.Type == DealType.Buy
405 | ? Sides.Buy
406 | : (deal.Type == DealType.Sell ? Sides.Sell : (Sides?)null)
407 | });
408 |
409 | TryFlushData(registry, securityId, format, ExecutionTypes.Tick, secData.Item2, reader);
410 | };
411 | break;
412 | }
413 | case StreamType.OrdLog:
414 | {
415 | ((IOrdLogStream)stream).Handler += ol =>
416 | {
417 | var currTransactionId = ol.DateTime.Ticks;
418 |
419 | if (lastTransactionId < currTransactionId)
420 | lastTransactionId = currTransactionId;
421 | else if (lastTransactionId >= currTransactionId)
422 | lastTransactionId++;
423 |
424 | var msg = new ExecutionMessage
425 | {
426 | LocalTime = ToLocalDto(reader.CurrentDateTime),
427 | ExecutionType = ExecutionTypes.OrderLog,
428 | SecurityId = securityId,
429 | OpenInterest = ol.OI == 0 ? (long?)null : ol.OI,
430 | OrderId = ol.OrderId,
431 | OrderPrice = priceStep * ol.Price,
432 | ServerTime = ToServerDto(ol.DateTime),
433 | OrderVolume = ol.Amount,
434 | Balance = ol.AmountRest,
435 | TradeId = ol.DealId == 0 ? (long?)null : ol.DealId,
436 | TradePrice = ol.DealPrice == 0 ? (decimal?)null : priceStep * ol.DealPrice,
437 | TransactionId = lastTransactionId
438 | };
439 |
440 | var status = 0;
441 |
442 | if (ol.Flags.Contains(OrdLogFlags.Add))
443 | {
444 | msg.OrderState = OrderStates.Active;
445 | }
446 | else if (ol.Flags.Contains(OrdLogFlags.Fill))
447 | {
448 | msg.OrderState = OrderStates.Done;
449 | }
450 | else if (ol.Flags.Contains(OrdLogFlags.Canceled))
451 | {
452 | msg.OrderState = OrderStates.Done;
453 | status |= 0x200000;
454 | }
455 | else if (ol.Flags.Contains(OrdLogFlags.CanceledGroup))
456 | {
457 | msg.OrderState = OrderStates.Done;
458 | status |= 0x400000;
459 | }
460 | else if (ol.Flags.Contains(OrdLogFlags.Moved))
461 | {
462 | status |= 0x100000;
463 | }
464 |
465 | if (ol.Flags.Contains(OrdLogFlags.Buy))
466 | {
467 | msg.Side = Sides.Buy;
468 | }
469 | else if (ol.Flags.Contains(OrdLogFlags.Sell))
470 | {
471 | msg.Side = Sides.Sell;
472 | }
473 |
474 | if (ol.Flags.Contains(OrdLogFlags.FillOrKill))
475 | {
476 | msg.TimeInForce = TimeInForce.MatchOrCancel;
477 | status |= 0x00080000;
478 | }
479 |
480 | if (ol.Flags.Contains(OrdLogFlags.Quote))
481 | {
482 | msg.TimeInForce = TimeInForce.PutInQueue;
483 | status |= 0x01;
484 | }
485 |
486 | if (ol.Flags.Contains(OrdLogFlags.Counter))
487 | {
488 | status |= 0x02;
489 | }
490 |
491 | if (ol.Flags.Contains(OrdLogFlags.CrossTrade))
492 | {
493 | status |= 0x20000000;
494 | }
495 |
496 | if (ol.Flags.Contains(OrdLogFlags.NonSystem))
497 | {
498 | msg.IsSystem = false;
499 | status |= 0x04;
500 | }
501 |
502 | if (ol.Flags.Contains(OrdLogFlags.EndOfTransaction))
503 | {
504 | status |= 0x1000;
505 | }
506 |
507 | msg.OrderStatus = status;
508 |
509 | if (builder == null)
510 | {
511 | secData.Item4.Add(msg);
512 |
513 | TryFlushData(registry, securityId, format, ExecutionTypes.OrderLog, secData.Item4, reader);
514 | }
515 | else
516 | {
517 | //if (builder.Depth.Bids.Any() || builder.Depth.Asks.Any() || msg.ServerTime.TimeOfDay >= new TimeSpan(0, 18, 45, 00, 1))
518 | {
519 | QuoteChangeMessage updated;
520 |
521 | try
522 | {
523 | updated = builder.Update(msg);
524 | }
525 | catch
526 | {
527 | updated = null;
528 | }
529 |
530 | if (updated != null)
531 | {
532 | secData.Item1.Add(updated);
533 |
534 | TryFlushData(registry, securityId, format, null, secData.Item1, reader);
535 | }
536 | }
537 | }
538 | };
539 | break;
540 | }
541 | case StreamType.AuxInfo:
542 | {
543 | ((IAuxInfoStream)stream).Handler += info =>
544 | {
545 | var l1Msg = new Level1ChangeMessage
546 | {
547 | LocalTime = ToLocalDto(reader.CurrentDateTime),
548 | SecurityId = securityId,
549 | ServerTime = ToLocalDto(reader.CurrentDateTime),
550 | }
551 | .TryAdd(Level1Fields.LastTradePrice, priceStep * info.Price)
552 | .TryAdd(Level1Fields.BidsVolume, (decimal)info.BidTotal)
553 | .TryAdd(Level1Fields.AsksVolume, (decimal)info.AskTotal)
554 | .TryAdd(Level1Fields.HighPrice, priceStep * info.HiLimit)
555 | .TryAdd(Level1Fields.LowPrice, priceStep * info.LoLimit)
556 | .TryAdd(Level1Fields.StepPrice, (decimal)info.Rate)
557 | .TryAdd(Level1Fields.OperatingMargin, (decimal)info.Deposit)
558 | .TryAdd(Level1Fields.OpenInterest, (decimal)info.OI);
559 |
560 | if (l1Msg.Changes.Count == 0)
561 | return;
562 |
563 | secData.Item3.Add(l1Msg);
564 |
565 | TryFlushData(registry, securityId, format, null, secData.Item3, reader);
566 | };
567 | break;
568 | }
569 | case StreamType.OwnOrders:
570 | case StreamType.OwnTrades:
571 | case StreamType.Messages:
572 | case StreamType.None:
573 | {
574 | continue;
575 | }
576 | default:
577 | throw new ArgumentOutOfRangeException("Неподдерживаемый тип потока {0}.".Put(stream.Type));
578 | }
579 | }
580 |
581 | if (data.Count > 0)
582 | {
583 | while (qr.CurrentDateTime != DateTime.MaxValue && _isStarted)
584 | qr.Read(true);
585 | }
586 | }
587 |
588 | if (!_isStarted)
589 | return;
590 |
591 | foreach (var pair in data)
592 | {
593 | if (pair.Value.Item1.Any())
594 | {
595 | registry.GetQuoteMessageStorage(pair.Key, registry.DefaultDrive, format).Save(pair.Value.Item1);
596 | }
597 |
598 | if (pair.Value.Item2.Any())
599 | {
600 | registry.GetTickMessageStorage(pair.Key, registry.DefaultDrive, format).Save(pair.Value.Item2);
601 | }
602 |
603 | if (pair.Value.Item3.Any())
604 | {
605 | registry.GetLevel1MessageStorage(pair.Key, registry.DefaultDrive, format).Save(pair.Value.Item3);
606 | }
607 |
608 | if (pair.Value.Item4.Any())
609 | {
610 | registry.GetOrderLogMessageStorage(pair.Key, registry.DefaultDrive, format).Save(pair.Value.Item4);
611 | }
612 | }
613 |
614 | if (data.Count > 0)
615 | {
616 | //File.AppendAllLines(_convertedFilesFile, new[] { fileNameKey });
617 | _convertedFiles.Add(fileNameKey);
618 | _convertedPerTaskPoolFiles.Add(fileNameKey);
619 | }
620 |
621 | _logManager.Application.AddInfoLog("Завершена конвертация файла {0}.", fileName);
622 | }
623 |
624 | private static SecurityId GetSecurityId(QScalp.Security security, string boardCode)
625 | {
626 | return new SecurityId
627 | {
628 | SecurityCode = security.Ticker,
629 | BoardCode = boardCode,
630 | };
631 | }
632 |
633 | private void TryEnable()
634 | {
635 | Convert.IsEnabled = !QshFolder.Folder.IsEmpty() && !StockSharpFolder.Folder.IsEmpty() && Board.SelectedBoard != null;
636 | }
637 |
638 | private void Board_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
639 | {
640 | TryEnable();
641 | }
642 |
643 | private void OnFolderChanged(string folder)
644 | {
645 | TryEnable();
646 | }
647 | }
648 | }
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using System.Windows;
4 |
5 | using StockSharp.Localization;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("Qsh2Bin")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("StockSharp")]
14 | [assembly: AssemblyProduct("Qsh2Bin")]
15 | [assembly: AssemblyCopyright("Copyright © StockSharp 2015")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion(ProjectDescriptions.Version)]
55 | [assembly: AssemblyFileVersion(ProjectDescriptions.Version)]
56 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace StockSharp.Qsh2StockSharp.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StockSharp.Qsh2StockSharp.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace StockSharp.Qsh2StockSharp.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/QScalp/DataTypes.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 |
14 | namespace QScalp
15 | {
16 | // ************************************************************************
17 |
18 | enum QuoteType { Unknown, Free, Spread, Ask, Bid, BestAsk, BestBid }
19 | enum DealType { Unknown, Buy, Sell }
20 | enum OwnOrderType { None, Regular, Stop }
21 | enum OwnTradeSource { Unknown, Real, Emulator, Manual, History }
22 | enum MessageType { None, Info, Warning, Error }
23 |
24 | // ************************************************************************
25 |
26 | struct Quote
27 | {
28 | public int Price;
29 | public int Volume;
30 | public QuoteType Type;
31 |
32 | public Quote(int price, int volume, QuoteType type)
33 | {
34 | this.Price = price;
35 | this.Volume = volume;
36 | this.Type = type;
37 | }
38 | }
39 |
40 | // ************************************************************************
41 |
42 | sealed class Deal
43 | {
44 | public DateTime DateTime;
45 | public long Id;
46 | public long OrderId;
47 | public DealType Type;
48 | public int Price;
49 | public int Volume;
50 | public int OI;
51 | }
52 |
53 | // ************************************************************************
54 |
55 | struct OwnOrder
56 | {
57 | public readonly OwnOrderType Type;
58 |
59 | public readonly long Id;
60 | public readonly int Price;
61 | public readonly int Quantity;
62 |
63 | public OwnOrder(long id, int price)
64 | {
65 | this.Type = OwnOrderType.None;
66 | this.Id = id;
67 | this.Price = price;
68 | this.Quantity = 0;
69 | }
70 |
71 | public OwnOrder(OwnOrderType type, long id, int price, int quantity)
72 | {
73 | this.Type = type;
74 | this.Id = id;
75 | this.Price = price;
76 | this.Quantity = quantity;
77 | }
78 | }
79 |
80 | // ************************************************************************
81 |
82 | sealed class OwnTrade
83 | {
84 | public readonly OwnTradeSource Source;
85 | public readonly DateTime DateTime;
86 | public readonly long TradeId;
87 | public readonly long OrderId;
88 | public readonly int Price;
89 | public readonly int Quantity;
90 |
91 | public OwnTrade(OwnTradeSource source, DateTime dateTime,
92 | long tradeId, long orderId, int price, int quantity)
93 | {
94 | this.Source = source;
95 | this.DateTime = dateTime;
96 | this.TradeId = tradeId;
97 | this.OrderId = orderId;
98 | this.Price = price;
99 | this.Quantity = quantity;
100 | }
101 | }
102 |
103 | // ************************************************************************
104 |
105 | struct Message
106 | {
107 | public readonly DateTime DateTime;
108 | public readonly MessageType Type;
109 | public readonly string Text;
110 |
111 | public Message(DateTime dateTime, MessageType type, string text)
112 | {
113 | this.DateTime = dateTime;
114 | this.Type = type;
115 | this.Text = text;
116 | }
117 | }
118 |
119 | // ************************************************************************
120 |
121 | sealed class AuxInfo
122 | {
123 | public readonly DateTime DateTime;
124 | public readonly int Price;
125 |
126 | public readonly int AskTotal;
127 | public readonly int BidTotal;
128 | public readonly int OI;
129 |
130 | public readonly int HiLimit;
131 | public readonly int LoLimit;
132 | public readonly double Deposit;
133 |
134 | public readonly double Rate;
135 | public readonly string Message;
136 |
137 | public AuxInfo(DateTime dateTime, int price, int askTotal, int bidTotal,
138 | int oi, int hiLimit, int loLimit, double deposit, double rate, string message)
139 | {
140 | this.DateTime = dateTime;
141 | this.Price = price;
142 |
143 | this.AskTotal = askTotal;
144 | this.BidTotal = bidTotal;
145 | this.OI = oi;
146 |
147 | this.HiLimit = hiLimit;
148 | this.LoLimit = loLimit;
149 | this.Deposit = deposit;
150 |
151 | this.Rate = rate;
152 | this.Message = message;
153 | }
154 | }
155 |
156 | // ************************************************************************
157 |
158 | [Flags]
159 | enum OrdLogFlags
160 | {
161 | NonZeroReplAct = 1 << 0,
162 | FlowStart = 1 << 1,
163 |
164 | Add = 1 << 2,
165 | Fill = 1 << 3,
166 |
167 | Buy = 1 << 4,
168 | Sell = 1 << 5,
169 |
170 | Snapshot = 1 << 6,
171 |
172 | Quote = 1 << 7, // Котировочная
173 | Counter = 1 << 8, // Встречная
174 | NonSystem = 1 << 9, // Внесистемная
175 | EndOfTransaction = 1 << 10, // Запись является последней в транзакции
176 | FillOrKill = 1 << 11, // Заявка Fill-or-kill
177 | Moved = 1 << 12, // Запись является результатом операции перемещения заявки
178 | Canceled = 1 << 13, // Запись является результатом операции удаления заявки
179 | CanceledGroup = 1 << 14, // Запись является результатом группового удаления
180 | CrossTrade = 1 << 15, // Признак удаления остатка заявки по причине кросс-сделки
181 |
182 | None = 0
183 | }
184 |
185 | // ************************************************************************
186 |
187 | sealed class OrdLogEntry
188 | {
189 | public readonly OrdLogFlags Flags;
190 |
191 | public readonly DateTime DateTime;
192 | public readonly long OrderId;
193 |
194 | public readonly int Price;
195 |
196 | public readonly int Amount;
197 | public readonly int AmountRest;
198 |
199 | public readonly long DealId;
200 | public readonly int DealPrice;
201 | public readonly int OI;
202 |
203 | public OrdLogEntry(OrdLogFlags flags, DateTime dateTime, long orderId,
204 | int price, int amount, int amountRest, long dealId, int dealPrice, int oi)
205 | {
206 | this.Flags = flags;
207 | this.DateTime = dateTime;
208 | this.OrderId = orderId;
209 | this.Price = price;
210 | this.Amount = amount;
211 | this.AmountRest = amountRest;
212 | this.DealId = dealId;
213 | this.DealPrice = dealPrice;
214 | this.OI = oi;
215 | }
216 | }
217 |
218 | // ************************************************************************
219 | }
220 |
--------------------------------------------------------------------------------
/QScalp/Internals/DateTimeHelper.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 |
14 | namespace QScalp.History.Internals
15 | {
16 | static class DateTimeHelper
17 | {
18 | // **********************************************************************
19 |
20 | public static long ToMs(DateTime dateTime)
21 | {
22 | return dateTime.Ticks / TimeSpan.TicksPerMillisecond;
23 | }
24 |
25 | // **********************************************************************
26 |
27 | public static DateTime FromMs(long milliseconds)
28 | {
29 | return new DateTime(milliseconds * TimeSpan.TicksPerMillisecond);
30 | }
31 |
32 | // **********************************************************************
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/QScalp/Internals/Flags.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 |
14 | namespace QScalp.History.Internals
15 | {
16 | // ************************************************************************
17 |
18 | [Flags]
19 | enum DealFlags
20 | {
21 | Type = 0x03,
22 |
23 | DateTime = 0x04,
24 | Id = 0x08,
25 | OrderId = 0x10,
26 | Price = 0x20,
27 | Volume = 0x40,
28 | OI = 0x80,
29 |
30 | None = 0
31 | }
32 |
33 | // **********************************************************************
34 |
35 | [Flags]
36 | enum OrderFlags
37 | {
38 | DropAll = 0x01,
39 | Active = 0x02,
40 | External = 0x04,
41 | Stop = 0x08,
42 |
43 | None = 0
44 | }
45 |
46 | // **********************************************************************
47 |
48 | [Flags]
49 | enum AuxInfoFlags
50 | {
51 | DateTime = 0x01,
52 |
53 | AskTotal = 0x02,
54 | BidTotal = 0x04,
55 | OI = 0x08,
56 | Price = 0x10,
57 |
58 | SessionInfo = 0x20,
59 | Rate = 0x40,
60 | Message = 0x80,
61 |
62 | None = 0
63 | }
64 |
65 | // ************************************************************************
66 |
67 | [Flags]
68 | enum OrdLogEntryFlags
69 | {
70 | DateTime = 0x01,
71 | OrderId = 0x02,
72 | Price = 0x04,
73 |
74 | Amount = 0x08,
75 | AmountRest = 0x10,
76 |
77 | DealId = 0x20,
78 | DealPrice = 0x40,
79 | OI = 0x80,
80 |
81 | None = 0
82 | }
83 |
84 | // ************************************************************************
85 | }
86 |
--------------------------------------------------------------------------------
/QScalp/Internals/Leb128.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System.IO;
13 |
14 | namespace QScalp.History.Internals
15 | {
16 | static class Leb128
17 | {
18 | // **********************************************************************
19 |
20 | public const int Min1BValue = -64;
21 | public const int Max1BValue = -Min1BValue - 1;
22 |
23 | public const int Min2BValue = -8192;
24 | public const int Max2BValue = -Min2BValue - 1;
25 |
26 | public const int Min3BValue = -1048576;
27 | public const int Max3BValue = -Min3BValue - 1;
28 |
29 | public const int Min4BValue = -134217728;
30 | public const int Max4BValue = -Min4BValue - 1;
31 |
32 | public const long Min5BValue = -17179869184;
33 | public const long Max5BValue = -Min5BValue - 1;
34 |
35 | public const long Min6BValue = -2199023255552;
36 | public const long Max6BValue = -Min6BValue - 1;
37 |
38 | public const long Min7BValue = -281474976710656;
39 | public const long Max7BValue = -Min7BValue - 1;
40 |
41 | public const long Min8BValue = -36028797018963968;
42 | public const long Max8BValue = -Min8BValue - 1;
43 |
44 | public const long Min9BValue = -4611686018427387904;
45 | public const long Max9BValue = -Min9BValue - 1;
46 |
47 | // **********************************************************************
48 |
49 | public static void Write(Stream stream, long value)
50 | {
51 | if(value >= 0)
52 | for(; ; )
53 | {
54 | int b = (int)(value & 0x7f);
55 | value >>= 7;
56 |
57 | if(value == 0 && (b & 0x40) == 0)
58 | {
59 | stream.WriteByte((byte)b);
60 | return;
61 | }
62 |
63 | stream.WriteByte((byte)(b | 0x80));
64 | }
65 | else
66 | for(; ; )
67 | {
68 | int b = (int)(value & 0x7f);
69 | value >>= 7;
70 |
71 | if(value == -1 && (b & 0x40) != 0)
72 | {
73 | stream.WriteByte((byte)b);
74 | return;
75 | }
76 |
77 | stream.WriteByte((byte)(b | 0x80));
78 | }
79 | }
80 |
81 | // **********************************************************************
82 |
83 | public static long Read(Stream stream)
84 | {
85 | long value = 0;
86 | int shift = 0;
87 |
88 | for(; ; )
89 | {
90 | int b = stream.ReadByte();
91 |
92 | if(b == -1)
93 | throw new EndOfStreamException();
94 |
95 | value |= (long)(b & 0x7f) << shift;
96 | shift += 7;
97 |
98 | if((b & 0x80) == 0)
99 | {
100 | if(shift < sizeof(long) * 8 && (b & 0x40) != 0)
101 | value |= -(1L << shift);
102 |
103 | return value;
104 | }
105 | }
106 | }
107 |
108 | // **********************************************************************
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/QScalp/Internals/QshFile.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.IO;
14 | using System.IO.Compression;
15 | using System.Text;
16 |
17 | namespace QScalp.History.Internals
18 | {
19 | static class QshFile
20 | {
21 | // **********************************************************************
22 |
23 | static readonly byte[] prefix = Encoding.ASCII.GetBytes("QScalp History Data");
24 |
25 | // **********************************************************************
26 |
27 | public static Stream Create(string path, bool compress, byte version)
28 | {
29 | Stream stm = new FileStream(path, FileMode.Create, FileAccess.Write);
30 |
31 | if(compress)
32 | stm = new GZipStream(stm, CompressionMode.Compress);
33 |
34 | stm.Write(prefix, 0, prefix.Length);
35 | stm.WriteByte(version);
36 |
37 | return stm;
38 | }
39 |
40 | // **********************************************************************
41 |
42 | static bool CheckPrefix(Stream stream, byte[] buffer)
43 | {
44 | if(stream.Read(buffer, 0, buffer.Length) != prefix.Length)
45 | return false;
46 |
47 | for(int i = 0; i < buffer.Length; i++)
48 | if(buffer[i] != prefix[i])
49 | return false;
50 |
51 | return true;
52 | }
53 |
54 | // **********************************************************************
55 |
56 | public static Stream GetDataStream(FileStream fs)
57 | {
58 | byte[] buffer = new byte[prefix.Length];
59 |
60 | if(CheckPrefix(fs, buffer))
61 | return fs;
62 |
63 | Stream stream = null;
64 |
65 | try
66 | {
67 | fs.Position = 0;
68 | stream = new GZipStream(fs, CompressionMode.Decompress, true);
69 |
70 | if(CheckPrefix(stream, buffer))
71 | return stream;
72 | }
73 | catch { }
74 |
75 | if(stream != null)
76 | {
77 | stream.Dispose();
78 | stream = null;
79 | }
80 |
81 | try
82 | {
83 | fs.Position = 0;
84 | stream = new DeflateStream(fs, CompressionMode.Decompress, true);
85 |
86 | if(CheckPrefix(stream, buffer))
87 | return stream;
88 | }
89 | catch { }
90 |
91 | if(stream != null)
92 | {
93 | stream.Dispose();
94 | stream = null;
95 | }
96 |
97 | throw new FormatException("Неверный формат файла");
98 | }
99 |
100 | // **********************************************************************
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/QScalp/Internals/StreamType.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | namespace QScalp.History
13 | {
14 | // ************************************************************************
15 |
16 | enum StreamType
17 | {
18 | Quotes = 0x10,
19 | Deals = 0x20,
20 | OwnOrders = 0x30,
21 | OwnTrades = 0x40,
22 | Messages = 0x50,
23 | AuxInfo = 0x60,
24 | OrdLog = 0x70,
25 | None = 0
26 | }
27 |
28 | // ************************************************************************
29 | }
30 |
--------------------------------------------------------------------------------
/QScalp/Internals/ULeb128.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System.IO;
13 |
14 | namespace QScalp.History.Internals
15 | {
16 | static class ULeb128
17 | {
18 | // **********************************************************************
19 |
20 | public const uint Max1BValue = 127;
21 | public const uint Max2BValue = 16383;
22 | public const uint Max3BValue = 2097151;
23 | public const uint Max4BValue = 268435455;
24 |
25 | // **********************************************************************
26 |
27 | public static void Write(Stream stream, uint value)
28 | {
29 | while(value > 127)
30 | {
31 | stream.WriteByte((byte)(value | 0x80));
32 | value >>= 7;
33 | }
34 |
35 | stream.WriteByte((byte)value);
36 | }
37 |
38 | // **********************************************************************
39 |
40 | public static uint Read(Stream stream)
41 | {
42 | uint value = 0;
43 | int shift = 0;
44 |
45 | for(; ; )
46 | {
47 | uint b = (uint)stream.ReadByte();
48 |
49 | if(b == 0xffffffff)
50 | throw new EndOfStreamException();
51 |
52 | value |= (b & 0x7f) << shift;
53 |
54 | if((b & 0x80) == 0)
55 | return value;
56 |
57 | shift += 7;
58 | }
59 | }
60 |
61 | // **********************************************************************
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/QScalp/RawQuotes.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System.Collections.Generic;
13 |
14 | namespace QScalp.Shared
15 | {
16 | sealed class RawQuotes : SortedDictionary
17 | {
18 | // **********************************************************************
19 |
20 | sealed class PriceComparer : IComparer
21 | {
22 | int IComparer.Compare(int x, int y)
23 | {
24 | if(x > y)
25 | return -1;
26 |
27 | if(x < y)
28 | return 1;
29 |
30 | return 0;
31 | }
32 | }
33 |
34 | // **********************************************************************
35 |
36 | public RawQuotes() : base(new PriceComparer()) { }
37 |
38 | // **********************************************************************
39 |
40 | public Quote[] GetQuotes()
41 | {
42 | Quote[] quotes = new Quote[this.Count];
43 |
44 | SortedDictionary.Enumerator enumerator = this.GetEnumerator();
45 | int index = -1;
46 |
47 | while(enumerator.MoveNext())
48 | {
49 | KeyValuePair kvp = enumerator.Current;
50 |
51 | if(kvp.Value > 0)
52 | {
53 | index++;
54 | quotes[index] = new Quote(kvp.Key, kvp.Value, QuoteType.Ask);
55 | }
56 | else if(kvp.Value < 0)
57 | {
58 | if(index >= 0)
59 | quotes[index].Type = QuoteType.BestAsk;
60 |
61 | index++;
62 | quotes[index] = new Quote(kvp.Key, -kvp.Value, QuoteType.BestBid);
63 |
64 | while(enumerator.MoveNext())
65 | {
66 | kvp = enumerator.Current;
67 |
68 | if(kvp.Value < 0)
69 | {
70 | index++;
71 | quotes[index] = new Quote(kvp.Key, -kvp.Value, QuoteType.Bid);
72 | }
73 | }
74 |
75 | return quotes;
76 | }
77 | }
78 |
79 | if(index >= 0)
80 | quotes[index].Type = QuoteType.BestAsk;
81 |
82 | return quotes;
83 | }
84 |
85 | // **********************************************************************
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/QScalp/Reader/IQshStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 |
14 | namespace QScalp.History.Reader
15 | {
16 | // ************************************************************************
17 |
18 | interface IQshStream { StreamType Type { get; } }
19 | interface ISecurityStream : IQshStream { Security Security { get; } }
20 |
21 | interface IQuotesStream : ISecurityStream { event Action Handler; }
22 | interface IDealsStream : ISecurityStream { event Action Handler; }
23 | interface IOwnOrdersStream : ISecurityStream { event Action Handler; }
24 | interface IOwnTradesStream : ISecurityStream { event Action Handler; }
25 | interface IMessagesStream : IQshStream { event Action Handler; }
26 | interface IAuxInfoStream : ISecurityStream { event Action Handler; }
27 | interface IOrdLogStream : ISecurityStream { event Action Handler; }
28 |
29 | // ************************************************************************
30 | }
31 |
--------------------------------------------------------------------------------
/QScalp/Reader/QshReader.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.IO;
14 |
15 | using QScalp.History.Internals;
16 |
17 | namespace QScalp.History.Reader
18 | {
19 | abstract class QshReader : IDisposable
20 | {
21 | // **********************************************************************
22 |
23 | public static QshReader Open(string path)
24 | {
25 | FileStream fs = null;
26 |
27 | try
28 | {
29 | fs = new FileStream(path, FileMode.Open, FileAccess.Read);
30 |
31 | Stream ds = QshFile.GetDataStream(fs);
32 | int version = ds.ReadByte();
33 |
34 | switch(version)
35 | {
36 | case 4: return new V4.QshReaderImpl(fs, ds);
37 |
38 | default:
39 | throw new FormatException("Неподдерживаемая версия файла (" + version + ")");
40 | }
41 | }
42 | catch
43 | {
44 | if(fs != null)
45 | fs.Dispose();
46 |
47 | throw;
48 | }
49 | }
50 |
51 | // **********************************************************************
52 |
53 | readonly FileStream fs;
54 |
55 | // **********************************************************************
56 |
57 | public long FileSize { get { return fs.Length; } }
58 | public long FilePosition { get { return fs.Position; } }
59 |
60 | public string AppName { get; protected set; }
61 | public string Comment { get; protected set; }
62 | public DateTime RecDateTime { get; protected set; }
63 |
64 | public abstract int StreamCount { get; }
65 | public abstract IQshStream this[int i] { get; }
66 |
67 | public DateTime CurrentDateTime { get; protected set; }
68 | public int CurrentStreamIndex { get; protected set; }
69 |
70 | // **********************************************************************
71 |
72 | protected QshReader(FileStream fs)
73 | {
74 | this.fs = fs;
75 | }
76 |
77 | // **********************************************************************
78 |
79 | public virtual void Dispose()
80 | {
81 | if(fs != null)
82 | fs.Dispose();
83 | }
84 |
85 | // **********************************************************************
86 |
87 | public abstract void Read(bool push);
88 |
89 | // **********************************************************************
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/AuxInfoStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Reader.V4
16 | {
17 | sealed class AuxInfoStream : QshStream, IAuxInfoStream
18 | {
19 | // **********************************************************************
20 |
21 | long lastMilliseconds;
22 | int lastAskTotal;
23 | int lastBidTotal;
24 | int lastOI;
25 | int lastPrice;
26 | int lastHiLimit;
27 | int lastLoLimit;
28 | double lastDeposit;
29 | double lastRate;
30 |
31 | // **********************************************************************
32 |
33 | public Security Security { get; private set; }
34 | public event Action Handler;
35 |
36 | // **********************************************************************
37 |
38 | public AuxInfoStream(DataReader dr)
39 | : base(StreamType.AuxInfo, dr)
40 | {
41 | Security = new Security(dr.ReadString());
42 | }
43 |
44 | // **********************************************************************
45 |
46 | public override void Read(bool push)
47 | {
48 | AuxInfoFlags flags = (AuxInfoFlags)dr.ReadByte();
49 | string message;
50 |
51 | // ------------------------------------------------------------
52 |
53 | if((flags & AuxInfoFlags.DateTime) != 0)
54 | lastMilliseconds = dr.ReadGrowing(lastMilliseconds);
55 |
56 | if((flags & AuxInfoFlags.AskTotal) != 0)
57 | lastAskTotal += (int)dr.ReadLeb128();
58 |
59 | if((flags & AuxInfoFlags.BidTotal) != 0)
60 | lastBidTotal += (int)dr.ReadLeb128();
61 |
62 | if((flags & AuxInfoFlags.OI) != 0)
63 | lastOI += (int)dr.ReadLeb128();
64 |
65 | if((flags & AuxInfoFlags.Price) != 0)
66 | lastPrice += (int)dr.ReadLeb128();
67 |
68 | if((flags & AuxInfoFlags.SessionInfo) != 0)
69 | {
70 | lastHiLimit = (int)dr.ReadLeb128();
71 | lastLoLimit = (int)dr.ReadLeb128();
72 | lastDeposit = dr.ReadDouble();
73 | }
74 |
75 | if((flags & AuxInfoFlags.Rate) != 0)
76 | lastRate = dr.ReadDouble();
77 |
78 | if((flags & AuxInfoFlags.Message) != 0)
79 | message = dr.ReadString();
80 | else
81 | message = null;
82 |
83 | // ------------------------------------------------------------
84 |
85 | if(push && Handler != null)
86 | Handler(new AuxInfo(
87 | DateTimeHelper.FromMs(lastMilliseconds),
88 | lastPrice, lastAskTotal, lastBidTotal,
89 | lastOI, lastHiLimit, lastLoLimit,
90 | lastDeposit, lastRate, message));
91 | }
92 |
93 | // **********************************************************************
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/DataReader.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System.IO;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Reader.V4
16 | {
17 | sealed class DataReader : BinaryReader
18 | {
19 | // **********************************************************************
20 |
21 | public DataReader(Stream stream) : base(stream) { }
22 |
23 | // **********************************************************************
24 |
25 | public long ReadGrowing(long lastValue)
26 | {
27 | uint offset = ULeb128.Read(BaseStream);
28 |
29 | if(offset == ULeb128.Max4BValue)
30 | return lastValue + Leb128.Read(BaseStream);
31 | else
32 | return lastValue + offset;
33 | }
34 |
35 | // **********************************************************************
36 |
37 | public long ReadLeb128() { return Leb128.Read(BaseStream); }
38 |
39 | // **********************************************************************
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/DealsStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Reader.V4
16 | {
17 | sealed class DealsStream : QshStream, IDealsStream
18 | {
19 | // **********************************************************************
20 |
21 | long lastMilliseconds;
22 | long lastId;
23 | long lastOrderId;
24 | int lastPrice;
25 | int lastVolume;
26 | int lastOI;
27 |
28 | // **********************************************************************
29 |
30 | public Security Security { get; private set; }
31 | public event Action Handler;
32 |
33 | // **********************************************************************
34 |
35 | public DealsStream(DataReader dr)
36 | : base(StreamType.Deals, dr)
37 | {
38 | Security = new Security(dr.ReadString());
39 | }
40 |
41 | // **********************************************************************
42 |
43 | public override void Read(bool push)
44 | {
45 | DealFlags flags = (DealFlags)dr.ReadByte();
46 |
47 | // ------------------------------------------------------------
48 |
49 | if((flags & DealFlags.DateTime) != 0)
50 | lastMilliseconds = dr.ReadGrowing(lastMilliseconds);
51 |
52 | if((flags & DealFlags.Id) != 0)
53 | lastId = dr.ReadGrowing(lastId);
54 |
55 | if((flags & DealFlags.OrderId) != 0)
56 | lastOrderId += dr.ReadLeb128();
57 |
58 | if((flags & DealFlags.Price) != 0)
59 | lastPrice += (int)dr.ReadLeb128();
60 |
61 | if((flags & DealFlags.Volume) != 0)
62 | lastVolume = (int)dr.ReadLeb128();
63 |
64 | if((flags & DealFlags.OI) != 0)
65 | lastOI += (int)dr.ReadLeb128();
66 |
67 | // ------------------------------------------------------------
68 |
69 | if(push && Handler != null)
70 | Handler(new Deal()
71 | {
72 | DateTime = DateTimeHelper.FromMs(lastMilliseconds),
73 | Id = lastId,
74 | OrderId = lastOrderId,
75 | Type = (DealType)(flags & DealFlags.Type),
76 | Price = lastPrice,
77 | Volume = lastVolume,
78 | OI = lastOI
79 | });
80 | }
81 |
82 | // **********************************************************************
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/MessagesStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 |
14 | namespace QScalp.History.Reader.V4
15 | {
16 | sealed class MessagesStream : QshStream, IMessagesStream
17 | {
18 | // **********************************************************************
19 |
20 | public event Action Handler;
21 |
22 | // **********************************************************************
23 |
24 | public MessagesStream(DataReader dr) : base(StreamType.Messages, dr) { }
25 |
26 | // **********************************************************************
27 |
28 | public override void Read(bool push)
29 | {
30 | Message msg = new Message(new DateTime(dr.ReadInt64()),
31 | (MessageType)dr.ReadByte(), dr.ReadString());
32 |
33 | if(push && Handler != null)
34 | Handler(msg);
35 | }
36 |
37 | // **********************************************************************
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/OrdLogStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2018 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.Collections.Generic;
14 |
15 | using QScalp.History.Internals;
16 | using QScalp.Shared;
17 |
18 | namespace QScalp.History.Reader.V4
19 | {
20 | sealed class OrdLogStream : QshStream, IOrdLogStream, IQuotesStream, IDealsStream, IAuxInfoStream
21 | {
22 | // **********************************************************************
23 |
24 | readonly RawQuotes rawQuotes;
25 |
26 | Action quotesHandler;
27 | Action dealHandler;
28 | Action auxInfoHandler;
29 |
30 | long lastPushedDealId;
31 |
32 | // **********************************************************************
33 |
34 | long lastMilliseconds;
35 | long lastOrderId;
36 |
37 | int lastPrice;
38 |
39 | int lastAmount;
40 | int lastAmountRest;
41 |
42 | long lastDealId;
43 | int lastDealPrice;
44 | int lastOI;
45 |
46 | // **********************************************************************
47 |
48 | public Security Security { get; private set; }
49 | public event Action Handler;
50 |
51 | // **********************************************************************
52 |
53 | event Action IQuotesStream.Handler
54 | {
55 | add { quotesHandler += value; }
56 | remove { quotesHandler -= value; }
57 | }
58 |
59 | event Action IDealsStream.Handler
60 | {
61 | add { dealHandler += value; }
62 | remove { dealHandler -= value; }
63 | }
64 |
65 | event Action IAuxInfoStream.Handler
66 | {
67 | add { auxInfoHandler += value; }
68 | remove { auxInfoHandler -= value; }
69 | }
70 |
71 | // **********************************************************************
72 |
73 | public OrdLogStream(DataReader dr)
74 | : base(StreamType.OrdLog, dr)
75 | {
76 | Security = new Security(dr.ReadString());
77 | rawQuotes = new RawQuotes();
78 | }
79 |
80 | // **********************************************************************
81 |
82 | public override void Read(bool push)
83 | {
84 | DateTime dateTime;
85 | long orderId;
86 | int amountRest;
87 | long dealId;
88 | int dealPrice;
89 | int oi;
90 |
91 | // ------------------------------------------------------------
92 |
93 | OrdLogEntryFlags flags = (OrdLogEntryFlags)dr.ReadByte();
94 | OrdLogFlags ordLogFlags = (OrdLogFlags)dr.ReadUInt16();
95 |
96 | bool isAdd = (ordLogFlags & OrdLogFlags.Add) != 0;
97 | bool isFill = (ordLogFlags & OrdLogFlags.Fill) != 0;
98 |
99 | bool isBuy = (ordLogFlags & OrdLogFlags.Buy) != 0;
100 | bool isSell = (ordLogFlags & OrdLogFlags.Sell) != 0;
101 |
102 | // ------------------------------------------------------------
103 |
104 | if((flags & OrdLogEntryFlags.DateTime) != 0)
105 | lastMilliseconds = dr.ReadGrowing(lastMilliseconds);
106 |
107 | dateTime = DateTimeHelper.FromMs(lastMilliseconds);
108 |
109 | if((flags & OrdLogEntryFlags.OrderId) == 0)
110 | orderId = lastOrderId;
111 | else if(isAdd)
112 | orderId = lastOrderId = dr.ReadGrowing(lastOrderId);
113 | else
114 | orderId = lastOrderId + dr.ReadLeb128();
115 |
116 | if((flags & OrdLogEntryFlags.Price) != 0)
117 | lastPrice += (int)dr.ReadLeb128();
118 |
119 | if((flags & OrdLogEntryFlags.Amount) != 0)
120 | lastAmount = (int)dr.ReadLeb128();
121 |
122 | if(isFill)
123 | {
124 | if((flags & OrdLogEntryFlags.AmountRest) != 0)
125 | amountRest = lastAmountRest = (int)dr.ReadLeb128();
126 | else
127 | amountRest = lastAmountRest;
128 |
129 | if((flags & OrdLogEntryFlags.DealId) != 0)
130 | dealId = lastDealId = dr.ReadGrowing(lastDealId);
131 | else
132 | dealId = lastDealId;
133 |
134 | if((flags & OrdLogEntryFlags.DealPrice) != 0)
135 | dealPrice = lastDealPrice += (int)dr.ReadLeb128();
136 | else
137 | dealPrice = lastDealPrice;
138 |
139 | if((flags & OrdLogEntryFlags.OI) != 0)
140 | oi = lastOI += (int)dr.ReadLeb128();
141 | else
142 | oi = lastOI;
143 | }
144 | else
145 | {
146 | amountRest = isAdd ? lastAmount : 0;
147 | dealId = 0;
148 | dealPrice = 0;
149 | oi = 0;
150 | }
151 |
152 | // ------------------------------------------------------------
153 |
154 | if(Handler != null && push)
155 | Handler(new OrdLogEntry(
156 | ordLogFlags, dateTime, orderId, lastPrice,
157 | lastAmount, amountRest, dealId, dealPrice, oi));
158 |
159 | // ------------------------------------------------------------
160 |
161 | if((ordLogFlags & OrdLogFlags.FlowStart) != 0)
162 | rawQuotes.Clear();
163 |
164 | if(!(isBuy ^ isSell)
165 | || (ordLogFlags & OrdLogFlags.NonSystem) != 0
166 | || (ordLogFlags & OrdLogFlags.NonZeroReplAct) != 0)
167 | {
168 | return;
169 | }
170 |
171 | // ------------------------------------------------------------
172 |
173 | int quantity;
174 | rawQuotes.TryGetValue(lastPrice, out quantity);
175 |
176 | if(isAdd ? isSell : isBuy)
177 | quantity += lastAmount;
178 | else
179 | quantity -= lastAmount;
180 |
181 | if(quantity == 0)
182 | rawQuotes.Remove(lastPrice);
183 | else
184 | rawQuotes[lastPrice] = quantity;
185 |
186 | // ------------------------------------------------------------
187 |
188 | if(push)
189 | {
190 | if((ordLogFlags & OrdLogFlags.EndOfTransaction) != 0)
191 | {
192 | // В большинстве случаев нет необходимости делать все,
193 | // что в этом блоке, на каждый тик. Целесообразнее
194 | // отправлять эти данные по таймеру, раз в 5-15 мс.
195 |
196 | if(quotesHandler != null)
197 | quotesHandler(rawQuotes.GetQuotes());
198 |
199 | if(auxInfoHandler != null)
200 | {
201 | int askTotal = 0;
202 | int bidTotal = 0;
203 |
204 | foreach(KeyValuePair kvp in rawQuotes)
205 | if(kvp.Value > 0)
206 | askTotal += kvp.Value;
207 | else
208 | bidTotal -= kvp.Value;
209 |
210 | auxInfoHandler(new AuxInfo(
211 | dateTime, lastDealPrice, askTotal,
212 | bidTotal, lastOI, 0, 0, 0, 0, null));
213 | }
214 | }
215 |
216 | if(lastPushedDealId < dealId)
217 | {
218 | if(dealHandler != null)
219 | dealHandler(new Deal()
220 | {
221 | Type = isSell ? DealType.Sell : DealType.Buy,
222 | Id = dealId,
223 | DateTime = dateTime,
224 | Price = dealPrice,
225 | Volume = lastAmount,
226 | OI = oi
227 | });
228 |
229 | lastPushedDealId = dealId;
230 | }
231 | }
232 | }
233 |
234 | // **********************************************************************
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/OwnOrdersStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Reader.V4
16 | {
17 | sealed class OwnOrdersStream : QshStream, IOwnOrdersStream
18 | {
19 | // **********************************************************************
20 |
21 | public Security Security { get; private set; }
22 | public event Action Handler;
23 |
24 | // **********************************************************************
25 |
26 | public OwnOrdersStream(DataReader dr)
27 | : base(StreamType.OwnOrders, dr)
28 | {
29 | Security = new Security(dr.ReadString());
30 | }
31 |
32 | // **********************************************************************
33 |
34 | public override void Read(bool push)
35 | {
36 | OrderFlags flags = (OrderFlags)dr.ReadByte();
37 | OwnOrder order;
38 |
39 | if((flags & OrderFlags.DropAll) != 0)
40 | order = new OwnOrder();
41 | else
42 | {
43 | OwnOrderType type;
44 |
45 | if((flags & OrderFlags.Active) != 0)
46 | {
47 | if((flags & OrderFlags.Stop) != 0)
48 | type = OwnOrderType.Stop;
49 | else
50 | type = OwnOrderType.Regular;
51 | }
52 | else
53 | type = OwnOrderType.None;
54 |
55 | order = new OwnOrder(type, dr.ReadLeb128(),
56 | (int)dr.ReadLeb128(), (int)dr.ReadLeb128());
57 | }
58 |
59 | if(push && Handler != null)
60 | Handler(order);
61 | }
62 |
63 | // **********************************************************************
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/OwnTradesStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Reader.V4
16 | {
17 | sealed class OwnTradesStream : QshStream, IOwnTradesStream
18 | {
19 | // **********************************************************************
20 |
21 | long lastMilliseconds;
22 | long lastTradeId;
23 | long lastOrderId;
24 | int lastPrice;
25 |
26 | // **********************************************************************
27 |
28 | public Security Security { get; private set; }
29 | public event Action Handler;
30 |
31 | // **********************************************************************
32 |
33 | public OwnTradesStream(DataReader dr)
34 | : base(StreamType.OwnTrades, dr)
35 | {
36 | Security = new Security(dr.ReadString());
37 | }
38 |
39 | // **********************************************************************
40 |
41 | public override void Read(bool push)
42 | {
43 | lastMilliseconds = dr.ReadGrowing(lastMilliseconds);
44 |
45 | lastTradeId += dr.ReadLeb128();
46 | lastOrderId += dr.ReadLeb128();
47 | lastPrice += (int)dr.ReadLeb128();
48 |
49 | int quantity = (int)dr.ReadLeb128();
50 |
51 | if(push && Handler != null)
52 | Handler(new OwnTrade(
53 | OwnTradeSource.History, DateTimeHelper.FromMs(lastMilliseconds),
54 | lastTradeId, lastOrderId, lastPrice, quantity));
55 | }
56 |
57 | // **********************************************************************
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/QshReaderImpl.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.IO;
14 |
15 | using QScalp.History.Internals;
16 |
17 | namespace QScalp.History.Reader.V4
18 | {
19 | sealed class QshReaderImpl : QshReader
20 | {
21 | // **********************************************************************
22 |
23 | readonly DataReader dr;
24 | readonly QshStream[] streams;
25 |
26 | QshStream currentStream;
27 | long lastMilliseconds;
28 |
29 | // **********************************************************************
30 |
31 | public override int StreamCount { get { return streams.Length; } }
32 | public override IQshStream this[int i] { get { return streams[i]; } }
33 |
34 | // **********************************************************************
35 |
36 | public QshReaderImpl(FileStream fs, Stream ds)
37 | : base(fs)
38 | {
39 | dr = new DataReader(ds);
40 |
41 | AppName = dr.ReadString();
42 | Comment = dr.ReadString();
43 | RecDateTime = new DateTime(dr.ReadInt64(), DateTimeKind.Utc);
44 |
45 | lastMilliseconds = DateTimeHelper.ToMs(RecDateTime);
46 |
47 | int streamCount = dr.ReadByte();
48 |
49 | if(streamCount == 0)
50 | throw new Exception("Нет потоков данных");
51 |
52 | streams = new QshStream[streamCount];
53 |
54 | for(int i = 0; i < streams.Length; i++)
55 | {
56 | StreamType st = (StreamType)dr.ReadByte();
57 |
58 | switch(st)
59 | {
60 | case StreamType.Quotes:
61 | streams[i] = new QuotesStream(dr);
62 | break;
63 |
64 | case StreamType.Deals:
65 | streams[i] = new DealsStream(dr);
66 | break;
67 |
68 | case StreamType.OwnOrders:
69 | streams[i] = new OwnOrdersStream(dr);
70 | break;
71 |
72 | case StreamType.OwnTrades:
73 | streams[i] = new OwnTradesStream(dr);
74 | break;
75 |
76 | case StreamType.Messages:
77 | streams[i] = new MessagesStream(dr);
78 | break;
79 |
80 | case StreamType.AuxInfo:
81 | streams[i] = new AuxInfoStream(dr);
82 | break;
83 |
84 | case StreamType.OrdLog:
85 | streams[i] = new OrdLogStream(dr);
86 | break;
87 |
88 | default:
89 | throw new FormatException("Неизвестный тип данных: " + st);
90 | }
91 | }
92 |
93 | if(streams.Length == 1)
94 | currentStream = streams[0];
95 |
96 | ReadNextRecordHeader();
97 | }
98 |
99 | // **********************************************************************
100 |
101 | void ReadNextRecordHeader()
102 | {
103 | try
104 | {
105 | lastMilliseconds = dr.ReadGrowing(lastMilliseconds);
106 | CurrentDateTime = DateTimeHelper.FromMs(lastMilliseconds);
107 |
108 | if(streams.Length > 1)
109 | {
110 | CurrentStreamIndex = dr.ReadByte();
111 | currentStream = streams[CurrentStreamIndex];
112 | }
113 | }
114 | catch(EndOfStreamException)
115 | {
116 | CurrentDateTime = DateTime.MaxValue;
117 | }
118 | }
119 |
120 | // **********************************************************************
121 |
122 | public override void Read(bool push)
123 | {
124 | currentStream.Read(push);
125 | ReadNextRecordHeader();
126 | }
127 |
128 | // **********************************************************************
129 |
130 | public override void Dispose()
131 | {
132 | if(dr != null)
133 | dr.Dispose();
134 |
135 | base.Dispose();
136 | }
137 |
138 | // **********************************************************************
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/QshStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | namespace QScalp.History.Reader.V4
13 | {
14 | abstract class QshStream : IQshStream
15 | {
16 | // **********************************************************************
17 |
18 | public StreamType Type { get; private set; }
19 |
20 | // **********************************************************************
21 |
22 | protected readonly DataReader dr;
23 |
24 | // **********************************************************************
25 |
26 | protected QshStream(StreamType type, DataReader dr)
27 | {
28 | this.Type = type;
29 | this.dr = dr;
30 | }
31 |
32 | // **********************************************************************
33 |
34 | public abstract void Read(bool push);
35 |
36 | // **********************************************************************
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/QScalp/Reader/V4/QuotesStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.Shared;
14 |
15 | namespace QScalp.History.Reader.V4
16 | {
17 | sealed class QuotesStream : QshStream, IQuotesStream
18 | {
19 | // **********************************************************************
20 |
21 | readonly RawQuotes rawQuotes;
22 | int lastPrice;
23 |
24 | // **********************************************************************
25 |
26 | public Security Security { get; private set; }
27 | public event Action Handler;
28 |
29 | // **********************************************************************
30 |
31 | public QuotesStream(DataReader dr)
32 | : base(StreamType.Quotes, dr)
33 | {
34 | Security = new Security(dr.ReadString());
35 | rawQuotes = new RawQuotes();
36 | }
37 |
38 | // **********************************************************************
39 |
40 | public override void Read(bool push)
41 | {
42 | int n = (int)dr.ReadLeb128();
43 |
44 | for(int i = 0; i < n; i++)
45 | {
46 | lastPrice += (int)dr.ReadLeb128();
47 | int v = (int)dr.ReadLeb128();
48 |
49 | if(v == 0)
50 | rawQuotes.Remove(lastPrice);
51 | else
52 | rawQuotes[lastPrice] = v;
53 | }
54 |
55 | if(push && Handler != null)
56 | Handler(rawQuotes.GetQuotes());
57 | }
58 |
59 | // **********************************************************************
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/QScalp/Security.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.Globalization;
14 |
15 | namespace QScalp
16 | {
17 | sealed class Security
18 | {
19 | // **********************************************************************
20 |
21 | const int stepRoundDigits = 14;
22 | static readonly char[] sep = new char[] { ':' };
23 |
24 | double step, inverseStep;
25 |
26 | NumberFormatInfo priceFormat;
27 |
28 | // **********************************************************************
29 |
30 | public string Entry { get; private set; }
31 |
32 | public string CName { get; private set; }
33 | public string Ticker { get; private set; }
34 | public string AuxCode { get; private set; }
35 | public int Id { get; private set; }
36 |
37 | public double Step
38 | {
39 | get { return step; }
40 |
41 | private set
42 | {
43 | if(value > 0)
44 | step = Math.Round(value, stepRoundDigits);
45 | else
46 | step = 1;
47 |
48 | inverseStep = 1 / step;
49 |
50 | double d = step;
51 | int precision = 0;
52 |
53 | while(d != (int)(d) && precision <= stepRoundDigits)
54 | {
55 | d = Math.Round(d * 10, stepRoundDigits);
56 | precision++;
57 | }
58 |
59 | priceFormat.NumberDecimalDigits = precision;
60 | }
61 | }
62 |
63 | // **********************************************************************
64 |
65 | public Security(string entry)
66 | {
67 | priceFormat = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone();
68 |
69 | if(string.IsNullOrEmpty(entry))
70 | {
71 | this.Entry = string.Empty;
72 | Reset(string.Empty);
73 | return;
74 | }
75 |
76 | this.Entry = entry;
77 |
78 | string[] s = entry.Split(sep);
79 |
80 | if(s.Length == 5)
81 | {
82 | CName = s[0];
83 | Ticker = s[1];
84 | AuxCode = s[2];
85 |
86 | int id = 0;
87 |
88 | bool error = s[3].Length > 0 && !int.TryParse(s[3],
89 | NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out id);
90 |
91 | Id = id;
92 |
93 | if(double.TryParse(s[4], NumberStyles.Float,
94 | NumberFormatInfo.InvariantInfo, out step))
95 | {
96 | Step = step;
97 | }
98 | else
99 | {
100 | Step = 1;
101 | error = true;
102 | }
103 |
104 | if(error)
105 | Ticker = "{" + Ticker + "}";
106 | }
107 | else
108 | Reset("{err}");
109 | }
110 |
111 | // **********************************************************************
112 |
113 | void Reset(string state)
114 | {
115 | CName = Ticker = state;
116 | AuxCode = string.Empty;
117 | Id = 0;
118 | Step = 1;
119 | }
120 |
121 | // **********************************************************************
122 |
123 | public override string ToString()
124 | {
125 | if(Entry.Length == 0)
126 | return string.Empty;
127 |
128 | return CName + " / " + Ticker
129 | + (AuxCode.Length == 0 ? string.Empty : " " + AuxCode)
130 | + (Id == 0 ? string.Empty : " " + Id) + ", "
131 | + GetPrice(1).ToString("N", priceFormat) + " пт";
132 | }
133 |
134 | // **********************************************************************
135 |
136 | public int GetTicks(double price)
137 | {
138 | return (int)Math.Round(price * inverseStep);
139 | }
140 |
141 | // **********************************************************************
142 |
143 | public double GetPrice(double ticks) { return ticks * Step; }
144 |
145 | // **********************************************************************
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/QScalp/Writer/AuxInfoStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Writer
16 | {
17 | sealed class AuxInfoStream
18 | {
19 | // **********************************************************************
20 |
21 | readonly DataWriter dw;
22 | readonly int sid;
23 |
24 | // **********************************************************************
25 |
26 | long lastMilliseconds;
27 | int lastAskTotal;
28 | int lastBidTotal;
29 | int lastOI;
30 | int lastPrice;
31 | int lastHiLimit;
32 | int lastLoLimit;
33 | double lastDeposit;
34 | double lastRate;
35 |
36 | // **********************************************************************
37 |
38 | public AuxInfoStream(DataWriter dw, int sid, Security s)
39 | {
40 | this.dw = dw;
41 | this.sid = sid;
42 |
43 | dw.Write((byte)StreamType.AuxInfo);
44 | dw.Write(s.Entry);
45 | }
46 |
47 | // **********************************************************************
48 |
49 | public void Write(DateTime dateTime, AuxInfo auxInfo)
50 | {
51 | dw.WriteRecHeader(sid, dateTime);
52 |
53 | // --------------------------------------------------
54 |
55 | long milliseconds = DateTimeHelper.ToMs(auxInfo.DateTime);
56 | AuxInfoFlags flags = AuxInfoFlags.None;
57 |
58 | // --------------------------------------------------
59 |
60 | if(lastMilliseconds != milliseconds)
61 | flags |= AuxInfoFlags.DateTime;
62 |
63 | if(lastAskTotal != auxInfo.AskTotal)
64 | flags |= AuxInfoFlags.AskTotal;
65 |
66 | if(lastBidTotal != auxInfo.BidTotal)
67 | flags |= AuxInfoFlags.BidTotal;
68 |
69 | if(lastOI != auxInfo.OI)
70 | flags |= AuxInfoFlags.OI;
71 |
72 | if(lastPrice != auxInfo.Price)
73 | flags |= AuxInfoFlags.Price;
74 |
75 | if(lastHiLimit != auxInfo.HiLimit
76 | || lastLoLimit != auxInfo.LoLimit
77 | || lastDeposit != auxInfo.Deposit)
78 | {
79 | flags |= AuxInfoFlags.SessionInfo;
80 | }
81 |
82 | if(lastRate != auxInfo.Rate)
83 | flags |= AuxInfoFlags.Rate;
84 |
85 | if(auxInfo.Message != null)
86 | flags |= AuxInfoFlags.Message;
87 |
88 | // --------------------------------------------------
89 |
90 | dw.Write((byte)flags);
91 |
92 | // --------------------------------------------------
93 |
94 | if((flags & AuxInfoFlags.DateTime) != 0)
95 | dw.WriteGrowing(milliseconds, ref lastMilliseconds);
96 |
97 | if((flags & AuxInfoFlags.AskTotal) != 0)
98 | {
99 | dw.WriteLeb128(auxInfo.AskTotal - lastAskTotal);
100 | lastAskTotal = auxInfo.AskTotal;
101 | }
102 |
103 | if((flags & AuxInfoFlags.BidTotal) != 0)
104 | {
105 | dw.WriteLeb128(auxInfo.BidTotal - lastBidTotal);
106 | lastBidTotal = auxInfo.BidTotal;
107 | }
108 |
109 | if((flags & AuxInfoFlags.OI) != 0)
110 | {
111 | dw.WriteLeb128(auxInfo.OI - lastOI);
112 | lastOI = auxInfo.OI;
113 | }
114 |
115 | if((flags & AuxInfoFlags.Price) != 0)
116 | {
117 | dw.WriteLeb128(auxInfo.Price - lastPrice);
118 | lastPrice = auxInfo.Price;
119 | }
120 |
121 | if((flags & AuxInfoFlags.SessionInfo) != 0)
122 | {
123 | dw.WriteLeb128(auxInfo.HiLimit);
124 | dw.WriteLeb128(auxInfo.LoLimit);
125 | dw.Write(auxInfo.Deposit);
126 |
127 | lastHiLimit = auxInfo.HiLimit;
128 | lastLoLimit = auxInfo.LoLimit;
129 | lastDeposit = auxInfo.Deposit;
130 | }
131 |
132 | if((flags & AuxInfoFlags.Rate) != 0)
133 | {
134 | dw.Write(auxInfo.Rate);
135 | lastRate = auxInfo.Rate;
136 | }
137 |
138 | if((flags & AuxInfoFlags.Message) != 0)
139 | dw.Write(auxInfo.Message);
140 |
141 | // --------------------------------------------------
142 | }
143 |
144 | // **********************************************************************
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/QScalp/Writer/DataWriter.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.IO;
14 |
15 | using QScalp.History.Internals;
16 |
17 | namespace QScalp.History.Writer
18 | {
19 | sealed class DataWriter : BinaryWriter
20 | {
21 | // **********************************************************************
22 |
23 | readonly bool multistreamed;
24 | long lastMilliseconds;
25 |
26 | // **********************************************************************
27 |
28 | public int RecordCount { get; private set; }
29 |
30 | // **********************************************************************
31 |
32 | public DataWriter(Stream output, DateTime recDateTime, bool multistreamed)
33 | : base(output)
34 | {
35 | this.lastMilliseconds = DateTimeHelper.ToMs(recDateTime);
36 | this.multistreamed = multistreamed;
37 | }
38 |
39 | // **********************************************************************
40 |
41 | public void WriteRecHeader(int sid, DateTime dateTime)
42 | {
43 | WriteGrowing(DateTimeHelper.ToMs(dateTime), ref lastMilliseconds);
44 |
45 | if(multistreamed)
46 | Write((byte)sid);
47 |
48 | RecordCount++;
49 | }
50 |
51 | // **********************************************************************
52 |
53 | public void WriteLeb128(long value) { Leb128.Write(BaseStream, value); }
54 |
55 | // **********************************************************************
56 |
57 | public void WriteGrowing(long value, ref long lastValue)
58 | {
59 | long offset = value - lastValue;
60 |
61 | if(offset >= ULeb128.Max4BValue || offset < 0)
62 | {
63 | ULeb128.Write(BaseStream, ULeb128.Max4BValue);
64 | Leb128.Write(BaseStream, offset);
65 | }
66 | else
67 | ULeb128.Write(BaseStream, (uint)offset);
68 |
69 | lastValue = value;
70 | }
71 |
72 | // **********************************************************************
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/QScalp/Writer/DealsStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Writer
16 | {
17 | sealed class DealsStream
18 | {
19 | // **********************************************************************
20 |
21 | readonly DataWriter dw;
22 | readonly int sid;
23 | readonly Security s;
24 |
25 | long lastMilliseconds;
26 | long lastId;
27 | long lastOrderId;
28 | int lastPrice;
29 | int lastVolume;
30 | int lastOI;
31 |
32 | // **********************************************************************
33 |
34 | public DealsStream(DataWriter dw, int sid, Security s)
35 | {
36 | this.dw = dw;
37 | this.sid = sid;
38 | this.s = s;
39 |
40 | dw.Write((byte)StreamType.Deals);
41 | dw.Write(s.Entry);
42 | }
43 |
44 | // **********************************************************************
45 |
46 | public void Write(DateTime dateTime, Deal deal)
47 | {
48 | dw.WriteRecHeader(sid, dateTime);
49 |
50 | // ------------------------------------------------------------
51 |
52 | long milliseconds = DateTimeHelper.ToMs(deal.DateTime);
53 | DealFlags flags = (DealFlags)deal.Type & DealFlags.Type;
54 |
55 | if(lastMilliseconds != milliseconds)
56 | flags |= DealFlags.DateTime;
57 |
58 | if(deal.Id != 0)
59 | flags |= DealFlags.Id;
60 |
61 | if(lastOrderId != deal.OrderId)
62 | flags |= DealFlags.OrderId;
63 |
64 | if(lastPrice != deal.Price)
65 | flags |= DealFlags.Price;
66 |
67 | if(lastVolume != deal.Volume)
68 | flags |= DealFlags.Volume;
69 |
70 | if(lastOI != deal.OI)
71 | flags |= DealFlags.OI;
72 |
73 | // ------------------------------------------------------------
74 |
75 | dw.Write((byte)flags);
76 |
77 | // ------------------------------------------------------------
78 |
79 | if((flags & DealFlags.DateTime) != 0)
80 | dw.WriteGrowing(milliseconds, ref lastMilliseconds);
81 |
82 | if((flags & DealFlags.Id) != 0)
83 | dw.WriteGrowing(deal.Id, ref lastId);
84 |
85 | if((flags & DealFlags.OrderId) != 0)
86 | {
87 | dw.WriteLeb128(deal.OrderId - lastOrderId);
88 | lastOrderId = deal.OrderId;
89 | }
90 |
91 | if((flags & DealFlags.Price) != 0)
92 | {
93 | dw.WriteLeb128(deal.Price - lastPrice);
94 | lastPrice = deal.Price;
95 | }
96 |
97 | if((flags & DealFlags.Volume) != 0)
98 | {
99 | dw.WriteLeb128(deal.Volume);
100 | lastVolume = deal.Volume;
101 | }
102 |
103 | if((flags & DealFlags.OI) != 0)
104 | {
105 | dw.WriteLeb128(deal.OI - lastOI);
106 | lastOI = deal.OI;
107 | }
108 |
109 | // ------------------------------------------------------------
110 | }
111 |
112 | // **********************************************************************
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/QScalp/Writer/MessagesStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 |
14 | namespace QScalp.History.Writer
15 | {
16 | sealed class MessagesStream
17 | {
18 | // **********************************************************************
19 |
20 | readonly DataWriter dw;
21 | readonly int sid;
22 |
23 | // **********************************************************************
24 |
25 | public MessagesStream(DataWriter dw, int sid)
26 | {
27 | this.dw = dw;
28 | this.sid = sid;
29 |
30 | dw.Write((byte)StreamType.Messages);
31 | }
32 |
33 | // **********************************************************************
34 |
35 | public void Write(DateTime dateTime, Message msg)
36 | {
37 | dw.WriteRecHeader(sid, dateTime);
38 |
39 | dw.Write(msg.DateTime.Ticks);
40 | dw.Write((byte)msg.Type);
41 | dw.Write(msg.Text);
42 | }
43 |
44 | // **********************************************************************
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/QScalp/Writer/OrdLogStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Writer
16 | {
17 | sealed class OrdLogStream
18 | {
19 | // **********************************************************************
20 |
21 | readonly DataWriter dw;
22 | readonly int sid;
23 | readonly Security s;
24 |
25 | long lastMilliseconds;
26 | long lastOrderId;
27 |
28 | int lastPrice;
29 |
30 | int lastAmount;
31 | int lastAmountRest;
32 |
33 | long lastDealId;
34 | int lastDealPrice;
35 | int lastOI;
36 |
37 | // **********************************************************************
38 |
39 | public OrdLogStream(DataWriter dw, int sid, Security s)
40 | {
41 | this.dw = dw;
42 | this.sid = sid;
43 | this.s = s;
44 |
45 | dw.Write((byte)StreamType.OrdLog);
46 | dw.Write(s.Entry);
47 | }
48 |
49 | // **********************************************************************
50 |
51 | public void Write(DateTime dateTime, OrdLogEntry entry)
52 | {
53 | dw.WriteRecHeader(sid, dateTime);
54 |
55 | // ------------------------------------------------------------
56 |
57 | long milliseconds = DateTimeHelper.ToMs(entry.DateTime);
58 | OrdLogEntryFlags flags = OrdLogEntryFlags.None;
59 |
60 | // ------------------------------------------------------------
61 |
62 | if(lastMilliseconds != milliseconds)
63 | flags |= OrdLogEntryFlags.DateTime;
64 |
65 | if(lastOrderId != entry.OrderId)
66 | flags |= OrdLogEntryFlags.OrderId;
67 |
68 | if(lastPrice != entry.Price)
69 | flags |= OrdLogEntryFlags.Price;
70 |
71 | if(lastAmount != entry.Amount)
72 | flags |= OrdLogEntryFlags.Amount;
73 |
74 | if((entry.Flags & OrdLogFlags.Fill) != 0)
75 | {
76 | if(lastAmountRest != entry.AmountRest)
77 | flags |= OrdLogEntryFlags.AmountRest;
78 |
79 | if(lastDealId != entry.DealId)
80 | flags |= OrdLogEntryFlags.DealId;
81 |
82 | if(lastDealPrice != entry.DealPrice)
83 | flags |= OrdLogEntryFlags.DealPrice;
84 |
85 | if(lastOI != entry.OI)
86 | flags |= OrdLogEntryFlags.OI;
87 | }
88 |
89 | // ------------------------------------------------------------
90 |
91 | dw.Write((byte)flags);
92 |
93 | // ------------------------------------------------------------
94 |
95 | dw.Write((ushort)entry.Flags);
96 |
97 | if((flags & OrdLogEntryFlags.DateTime) != 0)
98 | dw.WriteGrowing(milliseconds, ref lastMilliseconds);
99 |
100 | if((flags & OrdLogEntryFlags.OrderId) != 0)
101 | {
102 | if((entry.Flags & OrdLogFlags.Add) != 0)
103 | dw.WriteGrowing(entry.OrderId, ref lastOrderId);
104 | else
105 | dw.WriteLeb128(entry.OrderId - lastOrderId);
106 | }
107 |
108 | if((flags & OrdLogEntryFlags.Price) != 0)
109 | {
110 | dw.WriteLeb128(entry.Price - lastPrice);
111 | lastPrice = entry.Price;
112 | }
113 |
114 | if((flags & OrdLogEntryFlags.Amount) != 0)
115 | {
116 | dw.WriteLeb128(entry.Amount);
117 | lastAmount = entry.Amount;
118 | }
119 |
120 | if((flags & OrdLogEntryFlags.AmountRest) != 0)
121 | {
122 | dw.WriteLeb128(entry.AmountRest);
123 | lastAmountRest = entry.AmountRest;
124 | }
125 |
126 | if((flags & OrdLogEntryFlags.DealId) != 0)
127 | dw.WriteGrowing(entry.DealId, ref lastDealId);
128 |
129 | if((flags & OrdLogEntryFlags.DealPrice) != 0)
130 | {
131 | dw.WriteLeb128(entry.DealPrice - lastDealPrice);
132 | lastDealPrice = entry.DealPrice;
133 | }
134 |
135 | if((flags & OrdLogEntryFlags.OI) != 0)
136 | {
137 | dw.WriteLeb128(entry.OI - lastOI);
138 | lastOI = entry.OI;
139 | }
140 |
141 | // ------------------------------------------------------------
142 | }
143 |
144 | // **********************************************************************
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/QScalp/Writer/OwnOrdersStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Writer
16 | {
17 | sealed class OwnOrdersStream
18 | {
19 | // **********************************************************************
20 |
21 | readonly DataWriter dw;
22 | readonly int sid;
23 |
24 | // **********************************************************************
25 |
26 | public OwnOrdersStream(DataWriter dw, int sid, Security s)
27 | {
28 | this.dw = dw;
29 | this.sid = sid;
30 |
31 | dw.Write((byte)StreamType.OwnOrders);
32 | dw.Write(s.Entry);
33 | }
34 |
35 | // **********************************************************************
36 |
37 | public void Write(DateTime dateTime, OwnOrder order)
38 | {
39 | dw.WriteRecHeader(sid, dateTime);
40 |
41 | if(order.Id == 0 && order.Price == 0)
42 | dw.Write((byte)OrderFlags.DropAll);
43 | else
44 | {
45 | OrderFlags flags;
46 |
47 | switch(order.Type)
48 | {
49 | case OwnOrderType.Regular:
50 | flags = OrderFlags.Active;
51 | break;
52 |
53 | case OwnOrderType.Stop:
54 | flags = OrderFlags.Active | OrderFlags.Stop;
55 | break;
56 |
57 | default:
58 | flags = OrderFlags.None;
59 | break;
60 | }
61 |
62 | if(order.Id > 0)
63 | flags |= OrderFlags.External;
64 |
65 | dw.Write((byte)flags);
66 | dw.WriteLeb128(order.Id);
67 | dw.WriteLeb128(order.Price);
68 | dw.WriteLeb128(order.Quantity);
69 | }
70 | }
71 |
72 | // **********************************************************************
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/QScalp/Writer/OwnTradesStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using QScalp.History.Internals;
14 |
15 | namespace QScalp.History.Writer
16 | {
17 | sealed class OwnTradesStream
18 | {
19 | // **********************************************************************
20 |
21 | readonly DataWriter dw;
22 | readonly int sid;
23 |
24 | long lastMilliseconds;
25 | long lastTradeId;
26 | long lastOrderId;
27 | int lastPrice;
28 |
29 | // **********************************************************************
30 |
31 | public OwnTradesStream(DataWriter dw, int sid, Security s)
32 | {
33 | this.dw = dw;
34 | this.sid = sid;
35 |
36 | dw.Write((byte)StreamType.OwnTrades);
37 | dw.Write(s.Entry);
38 | }
39 |
40 | // **********************************************************************
41 |
42 | public void Write(DateTime dateTime, OwnTrade trade)
43 | {
44 | dw.WriteRecHeader(sid, dateTime);
45 |
46 | dw.WriteGrowing(DateTimeHelper.ToMs(trade.DateTime), ref lastMilliseconds);
47 |
48 | dw.WriteLeb128(trade.TradeId - lastTradeId);
49 | lastTradeId = trade.TradeId;
50 |
51 | dw.WriteLeb128(trade.OrderId - lastOrderId);
52 | lastOrderId = trade.OrderId;
53 |
54 | dw.WriteLeb128(trade.Price - lastPrice);
55 | lastPrice = trade.Price;
56 |
57 | dw.WriteLeb128(trade.Quantity);
58 | }
59 |
60 | // **********************************************************************
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/QScalp/Writer/QshWriter.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.IO;
14 |
15 | using QScalp.History.Internals;
16 |
17 | namespace QScalp.History.Writer
18 | {
19 | sealed class QshWriter : IDisposable
20 | {
21 | // **********************************************************************
22 |
23 | const byte fileVersion = 4;
24 |
25 | readonly Stream fs;
26 | readonly DataWriter dw;
27 |
28 | int streamCount;
29 |
30 | // **********************************************************************
31 |
32 | public int RecordCount { get { return dw.RecordCount; } }
33 | public long FileSize { get { return fs.Length; } }
34 |
35 | // **********************************************************************
36 |
37 | public QshWriter(string path, bool compress, string appName,
38 | string comment, DateTime recDateTime, int streamCount)
39 | {
40 | if(streamCount < 0)
41 | throw new ArgumentOutOfRangeException("streamCount");
42 |
43 | if(streamCount > byte.MaxValue)
44 | throw new OverflowException("Слишком много потоков для записи");
45 |
46 | fs = QshFile.Create(path, compress, fileVersion);
47 | dw = new DataWriter(fs, recDateTime, streamCount > 1);
48 |
49 | dw.Write(appName);
50 | dw.Write(comment);
51 | dw.Write(recDateTime.Ticks);
52 | dw.Write((byte)streamCount);
53 | }
54 |
55 | // **********************************************************************
56 |
57 | public void Dispose()
58 | {
59 | if(dw != null)
60 | dw.Dispose();
61 |
62 | if(fs != null)
63 | fs.Dispose();
64 | }
65 |
66 | // **********************************************************************
67 |
68 | public QuotesStream CreateQuotesStream(Security s)
69 | {
70 | return new QuotesStream(dw, streamCount++, s);
71 | }
72 |
73 | public DealsStream CreateDealsStream(Security s)
74 | {
75 | return new DealsStream(dw, streamCount++, s);
76 | }
77 |
78 | public OwnOrdersStream CreateOwnOrdersStream(Security s)
79 | {
80 | return new OwnOrdersStream(dw, streamCount++, s);
81 | }
82 |
83 | public OwnTradesStream CreateOwnTradesStream(Security s)
84 | {
85 | return new OwnTradesStream(dw, streamCount++, s);
86 | }
87 |
88 | public MessagesStream CreateMessagesStream()
89 | {
90 | return new MessagesStream(dw, streamCount++);
91 | }
92 |
93 | public AuxInfoStream CreateAuxInfoStream(Security s)
94 | {
95 | return new AuxInfoStream(dw, streamCount++, s);
96 | }
97 |
98 | public OrdLogStream CreateOrdLogStream(Security s)
99 | {
100 | return new OrdLogStream(dw, streamCount++, s);
101 | }
102 |
103 | // **********************************************************************
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/QScalp/Writer/QuotesStream.cs:
--------------------------------------------------------------------------------
1 | #region Copyright (c) 2011-2016 Николай Морошкин, http://www.moroshkin.com/
2 | /*
3 |
4 | Настоящий исходный код является частью приложения «Торговый привод QScalp»
5 | (http://www.qscalp.ru) и предоставлен исключительно в ознакомительных
6 | целях. Какое-либо коммерческое использование данного кода без письменного
7 | разрешения автора запрещено.
8 |
9 | */
10 | #endregion
11 |
12 | using System;
13 | using System.Collections.Generic;
14 |
15 | namespace QScalp.History.Writer
16 | {
17 | sealed class QuotesStream
18 | {
19 | // **********************************************************************
20 |
21 | Quote[] lastQuotes = new Quote[0];
22 | readonly List diffQuotes = new List(100);
23 |
24 | int lastPrice;
25 |
26 | readonly DataWriter dw;
27 | readonly int sid;
28 |
29 | // **********************************************************************
30 |
31 | public QuotesStream(DataWriter dw, int sid, Security s)
32 | {
33 | this.dw = dw;
34 | this.sid = sid;
35 |
36 | dw.Write((byte)StreamType.Quotes);
37 | dw.Write(s.Entry);
38 | }
39 |
40 | // **********************************************************************
41 |
42 | static bool QuoteTypeEquals(QuoteType qt1, QuoteType qt2)
43 | {
44 | switch(qt1)
45 | {
46 | case QuoteType.Ask:
47 | case QuoteType.BestAsk:
48 | return qt2 == QuoteType.Ask || qt2 == QuoteType.BestAsk;
49 |
50 | case QuoteType.Bid:
51 | case QuoteType.BestBid:
52 | return qt2 == QuoteType.Bid || qt2 == QuoteType.BestBid;
53 |
54 | default:
55 | return qt1 == qt2;
56 | }
57 | }
58 |
59 | // **********************************************************************
60 |
61 | public void Write(DateTime dateTime, Quote[] quotes)
62 | {
63 | // ------------------------------------------------------------
64 |
65 | diffQuotes.Clear();
66 |
67 | int i = 0;
68 |
69 | foreach(Quote lq in lastQuotes)
70 | {
71 | while(i < quotes.Length && lq.Price < quotes[i].Price)
72 | diffQuotes.Add(quotes[i++]);
73 |
74 | if(i < quotes.Length && quotes[i].Price == lq.Price)
75 | {
76 | if(!QuoteTypeEquals(lq.Type, quotes[i].Type) || lq.Volume != quotes[i].Volume)
77 | diffQuotes.Add(quotes[i]);
78 |
79 | i++;
80 | }
81 | else
82 | diffQuotes.Add(new Quote(lq.Price, 0, QuoteType.Unknown));
83 | }
84 |
85 | while(i < quotes.Length)
86 | diffQuotes.Add(quotes[i++]);
87 |
88 | lastQuotes = quotes;
89 |
90 | // ------------------------------------------------------------
91 |
92 | if(diffQuotes.Count > 0)
93 | {
94 | dw.WriteRecHeader(sid, dateTime);
95 | dw.WriteLeb128(diffQuotes.Count);
96 |
97 | foreach(Quote q in diffQuotes)
98 | {
99 | dw.WriteLeb128(q.Price - lastPrice);
100 | lastPrice = q.Price;
101 |
102 | switch(q.Type)
103 | {
104 | case QuoteType.Ask:
105 | case QuoteType.BestAsk:
106 | dw.WriteLeb128(q.Volume);
107 | break;
108 |
109 | case QuoteType.Bid:
110 | case QuoteType.BestBid:
111 | dw.WriteLeb128(-q.Volume);
112 | break;
113 |
114 | default:
115 | dw.WriteLeb128(0);
116 | break;
117 | }
118 | }
119 | }
120 |
121 | // ------------------------------------------------------------
122 | }
123 |
124 | // **********************************************************************
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Qsh2StockSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {5B24FB13-5B07-4E9B-8C2E-02297BC1196E}
4 | WinExe
5 | StockSharp.Qsh2StockSharp
6 | netcoreapp3.1
7 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | false
9 | bin\$(Configuration)\
10 | true
11 | stocksharp.ico
12 |
13 |
14 | full
15 |
16 |
17 | none
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Qsh2StockSharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qsh2StockSharp", "Qsh2StockSharp.csproj", "{5B24FB13-5B07-4E9B-8C2E-02297BC1196E}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {5B24FB13-5B07-4E9B-8C2E-02297BC1196E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {5B24FB13-5B07-4E9B-8C2E-02297BC1196E}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {5B24FB13-5B07-4E9B-8C2E-02297BC1196E}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {5B24FB13-5B07-4E9B-8C2E-02297BC1196E}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Qsh -> StockSharp
2 | Программа конвертации маркет данных (стаканы, тики, ордер лог) из формата QScalp в формат StockSharp (bin или csv).
3 |
4 | Полученный формат поддерживается всеми программами, представленных на [сайте StockSharp](https://stocksharp.ru/products/).
5 |
6 | На текущий момент исходные данные доступны на сайте брокеров [ITInvest](https://iticapital.ru/software/additional-software/qscalp/) и [Церих](ftp://athistory.zerich.com/).
7 |
8 | Инструкция использования и обсуждение утилиты доступно на [форуме](https://stocksharp.ru/articles/322/konvertatsiya-istoricheskih-failov-qscalp-v-format-stocksharp/).
9 |
--------------------------------------------------------------------------------
/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/stocksharp.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StockSharp/Qsh2Bin/86e5cabed567664d187ef1aac85ab2f06887a61d/stocksharp.ico
--------------------------------------------------------------------------------