<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[QUIK -> DDE &mdash; Вывод исторических данных через pipe]]></title>
		<link>https://quik2dde.ru/viewtopic.php?id=19</link>
		<atom:link href="https://quik2dde.ru/extern.php?action=feed&amp;tid=19&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «Вывод исторических данных через pipe».]]></description>
		<lastBuildDate>Tue, 12 Feb 2013 04:07:38 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Вывод исторических данных через pipe]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=154#p154</link>
			<description><![CDATA[<p><strong>boris</strong>, Спасибо.<br />Я как раз над этим размышлял. Не знал куда и податься. Варианты какие-то неинтересные были.</p>]]></description>
			<author><![CDATA[null@example.com (ubase)]]></author>
			<pubDate>Tue, 12 Feb 2013 04:07:38 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=154#p154</guid>
		</item>
		<item>
			<title><![CDATA[Re: Вывод исторических данных через pipe]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=32#p32</link>
			<description><![CDATA[<p><strong>boris</strong>, большое вам спасибо за этот пример!</p>]]></description>
			<author><![CDATA[null@example.com (admin)]]></author>
			<pubDate>Thu, 20 Dec 2012 17:52:02 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=32#p32</guid>
		</item>
		<item>
			<title><![CDATA[Вывод исторических данных через pipe]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=27#p27</link>
			<description><![CDATA[<p>Хочу поделиться простой функцией экспорта данных графиков через pipe. Много работал с DDE серверами, но только недавно узнал про возможность такого простого экспорта данных через pipe. Открываем экспорт данных - данные для технического анализа, там выбираем инструмент, интервал и обязательно систему ТА - Amibroker. В общем-то все, после этого появится пайп с именем вида AmiBroker2QUIK_SBER@EQBR_1_1MINUTES, где SBER@EQBR_1 заданное мной имя. Теперь функция для чтения этого пайпа: </p><div class="codebox"><pre><code>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
{
    /// &lt;summary&gt;
    /// Логика взаимодействия для MainWindow.xaml
    /// &lt;/summary&gt;
    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 = &quot;AmiBroker2QUIK_SBER@EQBR_1_1MINUTES&quot;;
            if (System.IO.Directory.GetFiles(@&quot;\\.\pipe\&quot;).FirstOrDefault(p =&gt; p == &quot;\\\\.\\pipe\\&quot; + 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 &lt; 3) &amp;&amp; (Line != Environment.NewLine))
            { Line = &quot;0&quot; + Line; }
            Dispatcher.BeginInvoke(new Action(() =&gt;
            {
                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 &gt; 1024)
                {
                    do
                    {
                        bc = NamedPipe.Read(outByte, bc2, size - bc2);
                        bc2 = bc + bc2;
                    }
                    while (bc2 &lt; 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 &gt; 3)
                        {
                            if ((bytes[_cb - 3] == 7) &amp;&amp; (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 = &quot;&quot;;
                foreach (var b in bytes)
                {
                    if (cb &gt; 2)
                    {
                        if ((bytes[cb - 2] == 8) &amp;&amp; (b == 0) &amp;&amp; (!IsStream))
                        {
                            IsStream = true;
                        }
                    }
                    if (IsStream)
                    {
                        if ((i &gt;= 48) &amp;&amp; (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() + &quot;; &quot;;
                                outStr += pDate.ToString() + &quot;; &quot;;
                                outStr += Open.ToString() + &quot;; &quot;;
                                outStr += High.ToString() + &quot;; &quot;;
                                outStr += Low.ToString() + &quot;; &quot;;
                                outStr += Close.ToString() + &quot;; &quot;;
                                outStr += Volume.ToString();
                                outStr += Environment.NewLine;
                                cs++;
                            }
                        }
                        else
                        {
                            CandleBytes[i] = b;
                            ++i;
                        }
                    }
                    ++cb;
                }
                if (outStr != &quot;&quot;)
                {
                    WriteLine(outStr);
                }

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

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

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            UpdateChart();
        }
    }
}</code></pre></div><p>С разбором даты я не совсем до конца разобрался, но в таком виде корректно отображает с точностью до секунд. Ну и чтобы уж совсем автоматизировать выгрузку, можно самому формировать файлик metastok.dat - в нем содержатся параметры для выгрузки.</p>]]></description>
			<author><![CDATA[null@example.com (boris)]]></author>
			<pubDate>Thu, 20 Dec 2012 11:18:10 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=27#p27</guid>
		</item>
	</channel>
</rss>
