Простой пример закачки истории тиков с финама или другого источника

Простой пример закачки истории тиков с финама или другого источника
Atom
09.03.2015
dron3333


Всем привет! Только начал разбираться с библиотекой, новичек в общем я. Можете написать простой рабочий пример(кусок кода) закачки данных с финама, ну или с другого источника за период ну пусть пару дней по инструменту LKOH. Ну или хотя бы вообще хоть какой-нибудь примерчик. Никак разобраться не получается. Заранее спасибо

Теги:


Спасибо:


dron3333

Фотография
Дата: 10.03.2015
Ответить


Ребят, что никто не поможет?....
Спасибо:

VassilSanych

Фотография
Дата: 10.03.2015
Ответить


Загрузка из Гидры
Код
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Storages;
using StockSharp.BusinessEntities;
using StockSharp.Logging;
using Candle = VGn.Robot.Candle;

namespace VGn.Robot
{
	/// <summary>
	///  Класс предварительной подготовки данных
	/// </summary>
	public class DataLoader : BaseLogReceiver
	{
		LogManager logManager;
		IMarketDataStorage<Trade> tradesStorage;

		Security security;

		public DataLoader()
		{
			
			logManager = new LogManager();
			logManager.Listeners.Add(new FileLogListener(@"c:\candles.log"));
			logManager.Sources.Add(this);

			var path = Path.GetFullPath(@"c:\Hydra\");

			var storageRegistry = new StorageRegistry
			{
				// изменяем путь, используемый по умолчанию
				DefaultDrive = new LocalMarketDataDrive(path)
			};

			security = GenerateSecurity(); 

			tradesStorage = storageRegistry.GetTradeStorage(security);

		}


		public CandleSeries CreateTimeSeries(TimeSpan frameSize)
		{
			var candleFrame = "TimeFrameCandle";
			var candleFrameType = Type.GetType(string.Format("StockSharp.Algo.Candles.{0}, StockSharp.Algo", candleFrame), true);
			return new CandleSeries(
				candleFrameType, security, frameSize) { WorkingTime = ExchangeBoard.Forts.WorkingTime };
		}




		private static readonly string[] Mounths = { "H", "M", "U", "Z", }; // последовательность важна для правильной генерации имен фьючерсов
		public const int FIRST_YEAR = 2009;


		//todo: загрузка таблицы дат экспирации из файла
		public Dictionary<int, List<int>> FortsExpirationTable =
			new Dictionary<int, List<int>>()
			{
				{9, new List<int> {13,11,14,14}},
				{10, new List<int> {12,11,15,15}},
				{11, new List<int> {15,15,15,15}},
				{12, new List<int> {15,15,17,17}},
				{13, new List<int> {15,17,16,16}},
				{14, new List<int> {17,16,15,15}},
				{15, new List<int> {16,15,15,15}},
			};


		/// <summary>
		///  Создание склеенного фьючерса RI
		/// </summary>
		/// <returns></returns>
		public ContinuousSecurity GenerateSecurity()
		{
			var prefix = "RI";
			var securityName = prefix + "@CONTINIOUS";
			var result = new ContinuousSecurity
			{
				Id = securityName,
				Code = securityName,
				Name = "ContinuousSecurity for " + securityName,
				Board = ExchangeBoard.Forts,
			};
			for (var year = FIRST_YEAR; year < 2015; year++)
			{
				for (var i = 0; i < 4; i++)
				{
					var yearPart = year % 10;      // тут получаем последнюю цифру года
					var mounth = i * 3 + 3;
					var mounthPart = Mounths[i]; // тут выбирается индекс, показывающий месяц

					var id = prefix + mounthPart + yearPart + "@FORTS";
					var code = prefix + "-" + (yearPart) + "." + (mounth);
					var security = new Security
					{
						Id = id,
						Code = code,
						Name =
								"ContinuousSecurity for " + prefix + " expiration in " + mounth + "." +
								year,
						Board = ExchangeBoard.Forts,
					};
					var expiration = new DateTime(year, mounth, FortsExpirationTable[year - 2000][i]);
					result.ExpirationJumps.Add(security, expiration);
				}
			}
			return result;
		}


		/// <summary>
		/// Трансформация свечей в короткую форму 
		/// </summary>
		public IEnumerable<Candle> TransformCandles(CandleSeries series, DateTime startTime, DateTime stopTime)
		{
			var trades = tradesStorage.Load(startTime, stopTime);
			var id = 1;
			foreach (var candle in trades.ToCandles(series))
			{
				var mycandle = new Candle
				{
					Close = candle.ClosePrice,
					High = candle.HighPrice,
					Id = id++,
					Low = candle.LowPrice,
					Open = candle.OpenPrice,
					Volume = candle.TotalVolume,
					Time = candle.CloseTime
				};
				yield return mycandle;
				//CandleList.Add(mycandle);
			}
			//this.AddInfoLog("Количество свечек {0}", CandleList.Count);
			
		}



		/// <summary>
		///  Загрузка готовых свечек из файла
		///  с целью исключения повторного формирования списка свечей
		/// </summary>
		/// <param name="fileName"></param>
		/// <returns></returns>
		public static  T GetFromFile<T>(string fileName) where T : class
		{
			if (!File.Exists(fileName))
				return null;

			//if (File.GetLastWriteTime(fileName).Date.AddDays(1) < DateTime.Now)
			//{
			//	File.Delete(fileName);
			//	return null;
			//}

			using (Stream stream = File.Open(fileName, FileMode.Open))
			{
				var bin = new BinaryFormatter();
				var list = (T)bin.Deserialize(stream);
				return list;
			}
		}


		/// <summary>
		///  Сохранение готовых свечек в файл
		///  с целью исключения повторного формирования списка свечей в тот же день 
		/// </summary>
		/// <param name="fileName"></param>
		/// <param name="list"></param>
		public static void WriteToFile<T>(string fileName, T list)
		{
			var v = Path.GetPathRoot(fileName);
			var c = Directory.Exists(v);
			using (Stream stream = File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.Read))
			{
				var bin = new BinaryFormatter();
				bin.Serialize(stream, list);
			}
		}


	}
}
Спасибо: dron3333

VassilSanych

Фотография
Дата: 10.03.2015
Ответить


Загрузка вчерашних данных для торговли на Квике. Код старый - не факт, что работает с новым API.
Код
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Candles.Compression;
using StockSharp.Algo.History;
using StockSharp.Algo.History.Finam;
using StockSharp.Algo.History.Rts;
using StockSharp.Algo.Storages;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Logging;

namespace VgnRobot.RobotEngine
{
	/// <summary>
	///		Базовый класс для свечных стратегий
	/// </summary>
	public abstract class CandleStrategyBase : Strategy
	{
		public ITimeCheckProvider TimeCheckProvider { get; set; }
		public IStopProvider StopProvider { get; set; }


		//protected StopOrdersChecker stopOrdersChecker;
		public readonly SyncObject Locker = new SyncObject();
		
		protected CandleStrategyBase()
		{
			// добавление отдельного логирования стратегии
			LogManager = new LogManager();
			ExchangeBoard.Forts.ApplyHolidays2013();
			//ExchangeBoard.Forts.ApplyHolidays2012();
		}

		private void InitSettings()
		{
			decimal minStepPrice;
			MinStepPriceSetting = Settings.TryGetProperty("MinStepPrice", out minStepPrice, this)
															? minStepPrice
															: (decimal?)null;
		}

		private decimal? MinStepPriceSetting { get; set; }





		/// <summary>
		///  Настройки стратегии
		///	 (для доступа к общим настройкам из родителького класса)
		/// </summary>
		public System.Configuration.SettingsBase Settings { get; set; }

		public CandleSeries Series { get; private set; }
		public virtual string Description { get { return Name; } }
		public ITraderBuilder TraderBuilder { get; set; }
		public IPortfolioSelector PortfolioSelector { get; set; }
		public ISecuritySelector SecuritySelector { get; set; }
		public IVolumeSizer VolumeSizer { get; set; }
		public IHistoryCandleProvider HistoryCandleProvider { get; set; }
		public ISettingsProvider SettingsProvider { get; set; }

		/// <summary>
		///  Движок создания заявок
		/// </summary>
		public IOrderHelper OrderHelper { get; set; }
		
		public Unit PriceDelta { get; set; }

		public Type CandleFrameType { get; set; }
		/// <summary>
		///  Текстовая обёртка CandleFrameType. Работает в обе стороны.
		/// </summary>
		public string CandleFrame
		{
			get
			{
				return CandleFrameType.Name;
			} 
			set
			{
				CandleFrameType = Type.GetType(string.Format("StockSharp.Algo.Candles.{0}, StockSharp.Algo", value), true);
			}
		}
		public object FrameSize { get; set; }


		DateTime _strategyStartTime;


		//public IList<Candle> GetHistoryTrades(DateTime beginDate, DateTime endDate)
		//{
		//	string uri = GetInstrumentUrl(beginDate, endDate);
		//	WebRequest request = WebRequest.Create(uri);
		//	using (StreamReader sr = new StreamReader(request.GetResponse().GetResponseStream()))
		//	{
		//		IList<Candle> result = new CandleReader().ReadCandles(sr);
		//		return result;
		//	}
		//}


		#region AddHistoryCandles Загрузка исторических свечек за прошлый день

		/// <summary>
		///  Класс-затычка для хранилища истории
		/// </summary>
		private class DumbSecurityStorage : ISecurityStorage
		{
			private Security _security;

			public Security LoadBy(string fieldName, object fieldValue)
			{
				return _security;
			}

			public void Save(Security security)
			{
				_security = security;
			}
		}


		Trade ParseTrade(string finamString)
		{
				var culture = new CultureInfo(System.Threading.Thread.CurrentThread.CurrentCulture.Name) { NumberFormat = { NumberDecimalSeparator = "." } };

				var parts = finamString.Split(',');
				var trade = new Trade
					{
						Time = DateTime.ParseExact(parts[0] + parts[1], "yyyyMMddHHmmss", culture),
						Price = decimal.Parse(parts[2], culture),
						Volume = decimal.Parse(parts[3], culture),
						Id = long.Parse(parts[4]),
						Security = Security
					};
				return trade;
				//{
				//	//<DATE>,<TIME>,<LAST>,<VOL>,<ID>
				//	Time = DateTime.ParseExact(parts[0] + parts[1], "yyyyMMddHHmmss", CultureInfo.InvariantCulture),
				//	Price = decimal.Parse(parts[2], CultureInfo.CurrentCulture),
				//	Volume = decimal.Parse(parts[3], CultureInfo.CurrentCulture),
				//	Id = long.Parse(parts[4]),
				//	Security = Security,
				//};
		}


		/// <summary>
		///  Получение сделок из файла, загруженного вручную с Финама
		/// </summary>
		/// <param name="filePath"></param>
		/// <returns></returns>
		IEnumerable<Trade> GetTradesFromTxt(string filePath)
		{
			var tradeHistory = new List<Trade>();
			if (!File.Exists(filePath))
			{
				return tradeHistory;
			}
			var history = File.ReadAllLines(filePath).Select(ParseTrade);
			return history;
		}


		/// <summary>
		///  Получение сделок с сайта Финама
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		IEnumerable<Trade> GetTradesFromFinam(DateTime date)
		{
			var storage = new DumbSecurityStorage();
			storage.Save(Security);
			var source = new FinamHistorySource(storage) { DumpFolder = GetTempPath() };
			long finamMarketId;
			Settings.TryGetProperty("HistoryFinamMarketId", out finamMarketId);  //14 
			long finamSecurityId;
			Settings.TryGetProperty("HistoryFinamSecurityId", out finamSecurityId);  //82813; 
			Security.ExtensionInfo["FinamMarketId"] = finamMarketId;
			Security.ExtensionInfo["FinamSecurityId"] = finamSecurityId;
			return source.GetTrades(Security, date);
		}


		/// <summary>
		///  Получение сделок с FTP RTS
		/// </summary>
		/// <param name="date"></param>
		/// <param name="loadEvening"></param>
		/// <returns></returns>
		IEnumerable<Trade> GetTradesFromRts(DateTime date, bool loadEvening = false)
		{
			var storage = new DumbSecurityStorage();
			storage.Save(Security);
			var source = new RtsHistorySource(storage) { DumpFolder = GetTempPath(), LoadEveningSession = loadEvening};
			var trades = new Dictionary<Security, IList<Trade>>();
			source.LoadTrades(date, trades);
			if (!trades.ContainsKey(Security))
				throw new ApplicationException("Не получены данные за прошлый день");
			return trades[Security];
		}


		/// <summary>
		///  Папка временных файлов для всех способов загрузки
		/// </summary>
		/// <returns></returns>
		private string GetTempPath()
		{
			var tempPath = Path.Combine(@"E:\TradeStorage\", "TemporaryFiles");

			if (!Directory.Exists(tempPath))
				Directory.CreateDirectory(tempPath);

			return tempPath;
		}


		/// <summary>
		///  Получение даты прошлого дня с учётов выходных и праздников 
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		DateTime GetLastDateBefore(DateTime date)
		{
			do
			{
				date = date.AddDays(-1);
				if (ExchangeBoard.Forts.WorkingTime.IsTradeDate(date, true))
					return date;
			} while (true);
		}


		protected TradeStorageCandleBuilderSource HistorySource;

		/// <summary>
		///  Добавление в список свечей данных из хранилища
		/// </summary>
		private void AddHistoryCandles()
		{
			try
			{
				this.AddDebugLog("Загрузка сделок за прошлый день");
				var storageRegistry = new StorageRegistry();
				string tradeStoragePath;
				Settings.TryGetProperty("HistoryTradeStoragePath", out tradeStoragePath);
				((LocalMarketDataDrive) storageRegistry.DefaultDrive).Path = tradeStoragePath;
				var storage = storageRegistry.GetTradeStorage(Security);

				var thisDate = LoggingHelper.Now.Date;
				var lastDate = GetLastDateBefore(thisDate);

				string historySource;
				Settings.TryGetProperty("HistorySource", out historySource);
				switch (historySource)
				{
					case "RTS":
						if (!storage.Dates.Contains(thisDate))
						{
							this.AddDebugLog("Загрузка сделок с RTS");
							var trades = GetTradesFromRts(lastDate, true);
							//
							storage.Save(trades.Where(t => t.Time > lastDate && t.Price > 0));
							//пропуск закачки более старых (нужна закачка целыми днями) и игнорирование ошибки данных
							// на ftp ртс данные выложены по сессиям с 19.00 до 19.00

							//trades = GetTradesFromRts(thisDate, true);
							//storage.Save(trades.Where(t => t.Time < thisDate && t.Price > 0));
							//пропуск закачки сегодняшних и игнорирование ошибки данных
							//todo: обработка ошибок закачки (стратегия останавливается)
						}
						break;
					case "Finam":
						if (!storage.Dates.Contains(lastDate))
						{
							this.AddDebugLog("Загрузка сделок с Финама");
							var trades = GetTradesFromFinam(lastDate);
							storage.Save(trades);
						}
						break;
					default:
						if (!storage.Dates.Contains(lastDate))
						{
							this.AddDebugLog("Загрузка сделок из файла");
							//var trades = GetTradesFromTxt(@"E:\Downloads\RIH3_130312_130312.txt");
							var trades = GetTradesFromTxt(string.Format(
								"{0}{1}_{2}_{2}.txt",
								tradeStoragePath, Security.Code, lastDate));
							storage.Save(trades);
						}
						break;
				}

				// берём только сделки раньше тех, что есть в таблице
				var lastTimeSource = Trader.Trades.Select(t => t.Time).ToArray();
				var lastTime = lastTimeSource.Any() ? lastTimeSource.Min() : thisDate;
				HistorySource = new TradeStorageCandleBuilderSource
					{
						StorageRegistry = storageRegistry,
						Filter = trade => trade.Time > lastDate && trade.Time < lastTime,
					};
				TraderBuilder.CandleManager.Sources.OfType<TickCandleBuilder>().Single().Sources.Add(HistorySource);
			}
			catch (Exception ex)
			{
				this.AddErrorLog(ex);
			}
		}


		/// <summary>
		///  Очистка памяти от истории за прошлый день.
		/// </summary>
		protected void DeleteHistory()
		{
			if (HistorySource == null)
				return;
			var source = HistorySource;
			HistorySource = null;
			TraderBuilder.CandleManager.Sources.OfType<TickCandleBuilder>().Single().Sources.Remove(source);
			source.Dispose();
			GC.Collect(2, GCCollectionMode.Forced);
		}

		#endregion

		//readonly object _candleProcessLocker = new object();
		protected override void OnStarted()
		{
			try
			{
				InitSettings();
				Trader = TraderBuilder.BuildTrader();
				OrderHelper = TraderBuilder.OrderHelper;
				if (Trader == null)
					throw new ApplicationException(string.Format("Отсутствует трейдер {0}.", TraderBuilder.Title));
				_strategyStartTime = Trader.GetMarketTime(ExchangeBoard.Forts.Exchange);

				Portfolio = PortfolioSelector.GetPortfolio(Trader);
				if (Portfolio == null)
					throw new ApplicationException(string.Format("Отсутствует портфель {0}.", PortfolioSelector.Title));

				Security = SecuritySelector.GetSecurity(Trader);
				if (Security == null)
					throw new ApplicationException(string.Format("Отсутствует инструмент {0}.", SecuritySelector.Title));
				Trader.RegisterSecurity(Security);

				Trader.RegisterMarketDepth(Security);

				if (VolumeSizer != null)
				{
					Volume = VolumeSizer.GetVolume(Portfolio, Security);
					this.AddInfoLog("Объем: {0}", Volume);
				}

				AddHistoryCandles();

				Series = new CandleSeries(
					CandleFrameType, Security, FrameSize) { WorkingTime = ExchangeBoard.Forts.WorkingTime };
					// Если Security - это WeightedIndexSecurity, то _series не заполняется

				Series
					.WhenCandlesFinished()
					.Do(CandleFinishedCall)
					.Sync(Locker)
					.Apply(this);

				TraderBuilder.CandleManager.Start(Series);

				base.OnStarted();

			}
			catch (Exception ex)
			{
				this.AddErrorLog(ex);
				Stop();
			}
		}


		public event Action<Candle> CandleFinished;

		/// <summary>
		///  Свеча сформирована
		/// </summary>
		/// <param name="candle"></param>
		private void CandleFinishedCall(Candle candle)
		{
			try
			{
				//todo: померять время
				ProcessCandle(candle);
				if (CandleFinished != null)
					CandleFinished(candle); // стратегия уже должна обработать все индикаторы
			}
			catch (Exception ex)
			{
				this.AddErrorLog(ex);
			}
		}


		protected override void OnStopping()
		{
			//todo: закрытие позиций

			if (Security != null)
				Trader.UnRegisterMarketDepth(Security);
		}


		protected override void OnStopped()
		{
			base.OnStopped();
		}


		protected virtual void ProcessCandle(Candle candle)
		{}

		private decimal _minStepPrice;
		/// <summary>
		///  Получение минимального лота из настроек, потому что соответствующее свойство Security иногда глючит
		/// </summary>
		public decimal MinStepPrice
		{
			get
			{
				if (_minStepPrice == 0)
				{
					_minStepPrice = MinStepPriceSetting != null
						? MinStepPriceSetting.Value
						: Security.MinStepPrice;
				}
				return _minStepPrice;
			}
		}


		/// <summary>
		///  Получение лучшей цены из стакана (цены изнутри спреда).
		/// </summary>
		/// <param name="direction"></param>
		/// <returns></returns>
		public decimal GetBestInnerPrice(OrderDirections direction)
		{
			var price = direction == OrderDirections.Buy
										? (Security.BestBid != null ? Security.BestBid.Price + MinStepPrice : 0)
										: (Security.BestBid != null ? Security.BestAsk.Price - MinStepPrice : 0);
			return price;
		}


		/// <summary>
		///  Создание и регистрация лимитных заявок в рамках стратегии
		/// </summary>
		/// <param name="direction"></param>
		/// <param name="volume"></param>
		protected void SendStrategyOrders(OrderDirections direction, decimal volume)
		{
			try
			{
				CancelActiveOrders(o => o.Type == OrderTypes.Limit);

				//while (Position != Portfolio.GetPosition() || Orders.Any(o => o.State == OrderStates.Active))
				//{
				//	this.AddWarningLog("* Разбег позиций перед сделкой: PositionManager {0} Trader {1}",
				//		Position, Portfolio.GetPosition());
				//	Thread.Sleep(100);
				//}

				var price = GetBestInnerPrice(direction);
				var order = OrderHelper.CreateLimitOrder(
						Security,
						direction,
						volume,
						price,
						null);

				var newTradesRule = order.WhenNewTrades();
				newTradesRule.Do(OnStrategyTrades).Sync(Locker).Apply();

				TimeCheckProvider.CurrentWaiting = 0;
				this.AddInfoLog(
					"* Новая заявка: Объём {0} Цена {1} Направление {2}",
					volume, price, direction);
				RegisterOrder(order);
			}
			catch (Exception ex)
			{
				this.AddErrorLog("* Ошибка регистрации заявки: {0}", ex);
			}

		}


		/// <summary>
		///  Обработка получения новых сделок
		/// </summary>
		/// <param name="trades"></param>
		private void OnStrategyTrades(IEnumerable<MyTrade> trades)
		{
			//todo: логирование новых сделок здесь?
			// возможно стоит создать некий буфер, чтобы логировать и здесь и по событию получения сделок (здесь, наверное, быстрее)
			StopProvider.AddStops(trades);
		}





		public LogManager LogManager { get; set; }

		public IChartPresenter ChartPresenter { get; set; }
	}
}
Спасибо: dron3333

dron3333

Фотография
Дата: 10.03.2015
Ответить


Спасибо большое вам! Буду разбираться...
Спасибо:


Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy