Для изменения размера нажмите или перетащите
Создание источника

Программа S#.Data построена с использованием подключаемых расширений в виде источников данных. Все стандартные источники являются такими же расширения, и их можно удалить из программы. Для этого нужно в подпапке Plugins в директории, где установлена S#.Data удалить нужное подключение, которое представлено в виде dll. Точно так же добавляются новые. Например, когда нужно добавить источник рыночных данных с других ресурсов, которые не входят стандартно. Ниже представлен процесс создания источника для РТС, который входит стандартно.

Примечание Примечание
Все источники и сама программа S#.Data доступна в исходниках, и находится в репозитории StockSharp на GitHub.

Этапы создание источника

  1. Каждый источник должен реализовать интерфейс IHydraTask (или наследоваться от классов BaseHydraTask или ConnectorHydraTask):

    C#
    [TargetPlatform(Languages.Russian)]
    [TaskDoc("http://stocksharp.com/doc/html/0da19c49-1f11-455e-bbd5-c20e428e5149.htm")]
    [TaskIcon("rts_logo.png")]
    [TaskCategory(TaskCategories.Russia | TaskCategories.History |
        TaskCategories.Stock | TaskCategories.Free | TaskCategories.Ticks)]
    class RtsTask : BaseHydraTask
    {
        private RtsSettings _settings;
    
        protected override void ApplySettings(HydraTaskSettings settings)
        {
            _settings = new RtsSettings(settings);
    
            if (settings.IsDefault)
            {
                _settings.DayOffset = 3;
                _settings.StartFrom = RtsHistorySource.RtsMinAvaliableTime;
                _settings.UsdRurStartFrom = FortsDailyData.UsdRateMinAvailableTime;
                _settings.IsDownloadUsdRate = true;
                //_settings.UsdRateLastDate = FortsDailyData.UsdRateMinAvailableTime;
                _settings.IsSystemOnly = true;
                _settings.LoadEveningSession = false;
                _settings.SaveRtsStdTrades = false;
                _settings.SaveRtsStdCombinedOnly = false;
                _settings.Interval = TimeSpan.FromDays(1);
                _settings.IgnoreWeekends = true;
                _settings.UseTemporaryFiles = TempFiles.UseAndDelete;
            }
        }
    
        public override HydraTaskSettings Settings
        {
            get { return _settings; }
        }
    }
  2. Свойство IHydraTask.Settings используется для хранения настроек источника. Класс, возращаемый из данного свойства, должен быть наследником HydraTaskSettings:

    C#
    [TaskSettingsDisplayName("РТС")]
    [CategoryOrder("РТС", 0)]
    private sealed class RtsSettings : HydraTaskSettings
    {
        private const string _rtsStndard = "RTS Standard";
        private const string _usdRur = "USD/RUR";
    
        public RtsSettings(HydraTaskSettings settings)
            : base(settings)
        {
            ExtensionInfo.TryAdd("UseTemporaryFiles", TempFiles.UseAndDelete.To<string>());
        }
    
        [TaskCategory("РТС")]
        [DisplayNameLoc("Начальная дата")]
        [DescriptionLoc("С какой даты начать скачивать данные.")]
        [PropertyOrder(0)]
        public DateTime StartFrom
        {
            get { return ExtensionInfo["StartFrom"].To<DateTime>(); }
            set { ExtensionInfo["StartFrom"] = value.Ticks; }
        }
    
        [TaskCategory("РТС")]
        [DisplayNameLoc("Временной отступ")]
        [DescriptionLoc("Временной отступ в днях от текущей даты, который необходим для предотвращения скачивания неполных данных за текущую торговую сессию.")]
        [PropertyOrder(1)]
        public int DayOffset
        {
            get { return ExtensionInfo["DayOffset"].To<int>(); }
            set { ExtensionInfo["DayOffset"] = value; }
        }
    
        [TaskCategory("РТС")]
        [DisplayNameLoc("Системные сделки")]
        [DescriptionLoc("Передавать только системные сделки. По-умолчанию значение равно true.")]
        [PropertyOrder(3)]
        public bool IsSystemOnly
        {
            get { return (bool)ExtensionInfo["IsSystemOnly"]; }
            set { ExtensionInfo["IsSystemOnly"] = value; }
        }
    
        [TaskCategory("РТС")]
        [DisplayNameLoc("Вечерняя сессия")]
        [DescriptionLoc("Скачивать данные вечерней сессии.")]
        [PropertyOrder(4)]
        public bool LoadEveningSession
        {
            get { return (bool)ExtensionInfo["LoadEveningSession"]; }
            set { ExtensionInfo["LoadEveningSession"] = value; }
        }
    
        [TaskCategory("РТС")]
        [DisplayNameLoc("Выходные")]
        [DescriptionLoc("Игнорировать выходные и праздничные дни (не скачивать данные).")]
        [PropertyOrder(5)]
        public bool IgnoreWeekends
        {
            get { return (bool)ExtensionInfo["IgnoreWeekends"]; }
            set { ExtensionInfo["IgnoreWeekends"] = value; }
        }
    
        [TaskCategory("РТС")]
        [DisplayNameLoc("Временные файлы")]
        [DescriptionLoc("Временные файлы", true)]
        [PropertyOrder(6)]
        public TempFiles UseTemporaryFiles
        {
            get { return ExtensionInfo["UseTemporaryFiles"].To<TempFiles>(); }
            set { ExtensionInfo["UseTemporaryFiles"] = value.To<string>(); }
        }
    
        [Category(_usdRur)]
        [DisplayNameLoc("Скачать")]
        [DescriptionLoc("Закачивать ли индикативный курс USD/RUR.")]
        [PropertyOrder(0)]
        public bool IsDownloadUsdRate
        {
            get { return (bool)ExtensionInfo["IsDownloadUsdRate"]; }
            set { ExtensionInfo["IsDownloadUsdRate"] = value; }
        }
    
        [Category(_usdRur)]
        [DisplayNameLoc("Начальная дата")]
        [DescriptionLoc("С какой даты начать скачивать данные для USD/RUR.")]
        [PropertyOrder(1)]
        public DateTime UsdRurStartFrom
        {
            get { return (DateTime)ExtensionInfo["UsdRurStartFrom"]; }
            set { ExtensionInfo["UsdRurStartFrom"] = value; }
        }
    
        [Category(_rtsStndard)]
        [DisplayNameLoc("Скачать")]
        [DescriptionLoc("Скачивать данные для инструментов РТС Стандарт.")]
        [PropertyOrder(5)]
        public bool SaveRtsStdTrades
        {
            get { return (bool)ExtensionInfo["SaveRtsStdTrades"]; }
            set { ExtensionInfo["SaveRtsStdTrades"] = value; }
        }
    
        [Category(_rtsStndard)]
        [DisplayNameLoc("Склеивать")]
        [DescriptionLoc("Склеивать сделки для инструментов РТС Стандарт (сделки для T+N не разбиваются по папкам).")]
        [PropertyOrder(5)]
        public bool SaveRtsStdCombinedOnly
        {
            get { return (bool)ExtensionInfo["SaveRtsStdCombinedOnly"]; }
            set { ExtensionInfo["SaveRtsStdCombinedOnly"] = value; }
        }
    }
  3. Завершающим этапом необходимо реализовать метод BaseHydraTask.OnProcess, в котором реализуется логика скачивания маркет-данных. В случае с RtsTask, вся логика находится в самом S# и используется класс RtsHistorySource:

    C#
    protected override TimeSpan OnProcess()
    {
        var source = new RtsHistorySource
        {
            IsSystemOnly = _settings.IsSystemOnly,
            LoadEveningSession = _settings.LoadEveningSession,
            SaveRtsStdTrades = _settings.SaveRtsStdTrades,
            SaveRtsStdCombinedOnly = _settings.SaveRtsStdCombinedOnly
        };
    
        if (_settings.UseTemporaryFiles != TempFiles.NotUse)
            source.DumpFolder = GetTempPath();
    
        // если фильтр по инструментам выключен (выбран инструмент все инструменты)
        var allSecurity = this.GetAllSecurity();
        var usdRur = GetUsdRur(source.SecurityIdGenerator.GenerateId("USD/RUR", ExchangeBoard.Forts));
    
        var startDate = _settings.StartFrom;
        var endDate = DateTime.Today - TimeSpan.FromDays(_settings.DayOffset);
    
        var allDates = startDate.Range(endDate, TimeSpan.FromDays(1)).ToArray();
    
        var secMap = new HashSet<Security>();
    
        if (allSecurity == null)
            secMap.AddRange(Settings.Securities.Select(s => s.Security));
    
        foreach (var date in allDates)
        {
            if (!CanProcess())
                break;
    
            if (_settings.IgnoreWeekends && !ExchangeBoard.Forts.WorkingTime.IsTradeDate(date, true))
            {
                this.AddDebugLog(LocalizedStrings.WeekEndDate, date);
                continue;
            }
    
            this.AddInfoLog(LocalizedStrings.Str2823Params, date);
    
            var trades = source.LoadTrades(EntityRegistry.Securities, date);
    
            if (trades.Count == 0)
            {
                this.AddDebugLog(LocalizedStrings.NoData);
            }
            else
            {
                if (allSecurity == null)
                    trades = trades.Where(p => secMap.Contains(p.Key)).ToDictionary();
    
                foreach (var pair in trades)
                {
                    SaveSecurity(pair.Key);
                    SaveTrades(pair.Key, pair.Value);
                }
            }
    
            if (_settings.UseTemporaryFiles == TempFiles.UseAndDelete)
            {
                var dir = source.GetDumpFile(null, date, date, typeof(Trade), null);
    
                if (Directory.Exists(dir))
                    Directory.Delete(dir, true);
            }
    
            _settings.StartFrom = date.AddDays(1);
            SaveSettings();
        }
    
        if (_settings.IsDownloadUsdRate)
        {
            var usdRurStorage = StorageRegistry.GetTradeStorage(usdRur, _settings.Drive, _settings.StorageFormat);
    
            foreach (var date in _settings.UsdRurStartFrom
                .Range(endDate, TimeSpan.FromDays(1))
                .Except(usdRurStorage.Dates))
            {
                if (!CanProcess())
                    break;
    
                if (_settings.IgnoreWeekends && !usdRur.Board.WorkingTime.IsTradeDate(date, true))
                {
                    this.AddDebugLog(LocalizedStrings.WeekEndDate, date);
                    continue;
                }
    
                this.AddInfoLog(LocalizedStrings.Str2294Params, date, usdRur.Id);
    
                var rate = FortsDailyData.GetRate(usdRur, date, date.Add(TimeSpan.FromDays(1)));
    
                if (rate.Count == 0)
                {
                    this.AddDebugLog(LocalizedStrings.NoData);
                }
                else
                {
                    SaveTrades(usdRur, rate.Select(p => new Trade
                    {
                        Security = usdRur,
                        Price = p.Value,
                        Time = p.Key,
                    }).OrderBy(t => t.Time));    
                }
    
                _settings.UsdRurStartFrom = date.AddDays(1);
                SaveSettings();
            }    
        }
    
        if (CanProcess())
            this.AddInfoLog(LocalizedStrings.Str2300);
    
        return base.OnProcess();
    }