1

Тема: Вывод исторических данных через pipe

Хочу поделиться простой функцией экспорта данных графиков через pipe. Много работал с DDE серверами, но только недавно узнал про возможность такого простого экспорта данных через pipe. Открываем экспорт данных - данные для технического анализа, там выбираем инструмент, интервал и обязательно систему ТА - Amibroker. В общем-то все, после этого появится пайп с именем вида AmiBroker2QUIK_SBER@EQBR_1_1MINUTES, где SBER@EQBR_1 заданное мной имя. Теперь функция для чтения этого пайпа:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.ComponentModel;
using System.Timers;
using System.Linq;

namespace TestPipe
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        protected override void OnClosing(CancelEventArgs e)
        {
            if (pipe != null)
            {
                pipe.Dispose();
            }
        }

        System.Timers.Timer _Timer = new System.Timers.Timer();
        NamedPipeClientStream pipe;
        public MainWindow()
        {
            InitializeComponent();
            string pipeName = "AmiBroker2QUIK_SBER@EQBR_1_1MINUTES";
            if (System.IO.Directory.GetFiles(@"\\.\pipe\").FirstOrDefault(p => p == "\\\\.\\pipe\\" + pipeName) != null)
            {
                pipe = new NamedPipeClientStream(pipeName);
                bool cr = pipe.CanRead;
                pipe.Connect();
                _Timer.Elapsed += UpdateChart;
            }
            else 
            { 
                pipe = null;
            }
        }

        public void WriteLine(string Line)
        {
            if ((Line.Length < 3) && (Line != Environment.NewLine))
            { Line = "0" + Line; }
            Dispatcher.BeginInvoke(new Action(() =>
            {
                this.textBox1.Text = this.textBox1.Text + Line;
            }));
        }

        private byte[] ReadPipe(NamedPipeClientStream NamedPipe, int size)
        {
            int bc = 0;
            int bc2 = 0;
            byte[] outByte = new byte[size];
            try
            {
                if (size > 1024)
                {
                    do
                    {
                        bc = NamedPipe.Read(outByte, bc2, size - bc2);
                        bc2 = bc + bc2;
                    }
                    while (bc2 < size);
                }
                else
                {
                    bc = NamedPipe.Read(outByte, 0, size);
                    bc2 = bc;
                }
            }
            catch { }
            return outByte.Take(bc2).ToArray();
        }

        int i = 0;
        byte[] CandleBytes = new byte[48];
        bool IsStream = false;
        bool IsFirstRead = true;
        int BarCount = 0;
        int cs = 0;
        private void UpdateChart(object sender, ElapsedEventArgs args)
        {
            UpdateChart();
        }

        int size = 1024;
        private void UpdateChart()
        {
            if (pipe != null)
            {

                byte[] bytes;
                if (IsFirstRead)
                {
                    bytes = ReadPipe(pipe, size);
                    int _cb = 0;
                    foreach (var b in bytes)
                    {
                        if (_cb > 3)
                        {
                            if ((bytes[_cb - 3] == 7) && (bytes[_cb - 2] == 0))
                            {
                                byte[] BarCountB = bytes.Skip(_cb - 1).Take(2).ToArray();
                                BarCount = BitConverter.ToInt16(BarCountB, 0);
                                size = (BarCount + 36) * 49;
                                break;
                            }
                        }
                        _cb++;
                    }
                }
                else
                {
                    bytes = ReadPipe(pipe, size);
                    size = 1024;
                }

                int cb = 0;
                string outStr = "";
                foreach (var b in bytes)
                {
                    if (cb > 2)
                    {
                        if ((bytes[cb - 2] == 8) && (b == 0) && (!IsStream))
                        {
                            IsStream = true;
                        }
                    }
                    if (IsStream)
                    {
                        if ((i >= 48) && (IsStream))
                        {
                            i = 0;
                            byte[] CandleBytes2 = CandleBytes;
                            CandleBytes = new byte[48];
                            IsStream = false;
                            byte[] dateB = CandleBytes2.Take(8).ToArray();
                            long dDate = BitConverter.ToInt64(dateB, 0);
                            if (dDate != 0)
                            {
                                DateTime pDate = (new DateTime(1970, 1, 1, 4, 0, 0, 0)).AddSeconds(Convert.ToInt64(dDate.ToString().Substring(0, 11)) - 11644488000);
                                byte[] OpenB = CandleBytes2.Skip(8).Take(8).ToArray();
                                double Open = BitConverter.ToDouble(OpenB, 0);
                                byte[] HighB = CandleBytes2.Skip(16).Take(8).ToArray();
                                double High = BitConverter.ToDouble(HighB, 0);
                                byte[] LowB = CandleBytes2.Skip(24).Take(8).ToArray();
                                double Low = BitConverter.ToDouble(LowB, 0);
                                byte[] CloseB = CandleBytes2.Skip(32).Take(8).ToArray();
                                double Close = BitConverter.ToDouble(CloseB, 0);
                                byte[] VolumeB = CandleBytes2.Skip(40).Take(8).ToArray();
                                double Volume = BitConverter.ToDouble(VolumeB, 0);

                                outStr += cs.ToString() + "; ";
                                outStr += pDate.ToString() + "; ";
                                outStr += Open.ToString() + "; ";
                                outStr += High.ToString() + "; ";
                                outStr += Low.ToString() + "; ";
                                outStr += Close.ToString() + "; ";
                                outStr += Volume.ToString();
                                outStr += Environment.NewLine;
                                cs++;
                            }
                        }
                        else
                        {
                            CandleBytes[i] = b;
                            ++i;
                        }
                    }
                    ++cb;
                }
                if (outStr != "")
                {
                    WriteLine(outStr);
                }

                if ((!IsFirstRead)&&(_Timer.Interval != 200))
                {
                    _Timer.Interval = 200;
                    _Timer.Start();
                }

                if (IsFirstRead)
                {
                    IsFirstRead = false;
                    UpdateChart();
                }
            }
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            UpdateChart();
        }
    }
}

С разбором даты я не совсем до конца разобрался, но в таком виде корректно отображает с точностью до секунд. Ну и чтобы уж совсем автоматизировать выгрузку, можно самому формировать файлик metastok.dat - в нем содержатся параметры для выгрузки.

2

Re: Вывод исторических данных через pipe

boris, большое вам спасибо за этот пример!

3 (2013-02-12 08:07:55 отредактировано ubase)

Re: Вывод исторических данных через pipe

boris, Спасибо.
Я как раз над этим размышлял. Не знал куда и податься. Варианты какие-то неинтересные были.