← Zurück

интерфейс ICandleSource

Доброе время суток. Можете показать пример реализации интерфейса ICandleSource?

Kommentare (6)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Mikhail Sukhov
Mikhail Sukhov

Дмитрий: Доброе время суток. Можете показать пример реализации интерфейса ICandleSource?

Посмотрите те, что идут стандартно в S#. Какое поведение хотите добиться?

Дмитрий
Дмитрий Autor

Мне надо на график выводить данные из массива (не из объекта trader). В примерах есть что-то подобное? Я не совсем понимаю, как реализовать методы addTrade и getTrades. Да и с событием не совсем понятно ) Как его фаерить, если у меня массив на входе?

Может у Вас были похожие задачи, где этот интерфес реализовывался для каких-то целей? Кусок кода бы...

Mikhail Sukhov
Mikhail Sukhov

Дмитрий: Мне надо на график выводить данные из массива (не из объекта trader). В примерах есть что-то подобное? Я не совсем понимаю, как реализовать методы addTrade и getTrades. Да и с событием не совсем понятно ) Как его фаерить, если у меня массив на входе?

Может у Вас были похожие задачи, где этот интерфес реализовывался для каких-то целей? Кусок кода бы...

Как-то так:

class MySource : ICandleSource
{
   public void AddTrades(Trade[] array)
   {
      /* нужно куда то сохранить для ICandleSource.Trades */
      NewTrades.SafeInvoke(array);
   }
}

и из кода соответственно вызывать метод AddTrades

Дмитрий
Дмитрий Autor

А можете релизацию этого интерфейса в объекте trader показать? Пусть даже сильно обрезанную. Чтобы все методы и событие интерфейса были описаны. Честно говоря, из этого кода по-прежнему не ясно, что делать.

Я правильно понял, что мой класс будет забирать данные из массива, и класть их в MySource.Trades именно в методе AddTrades? И какая специфика есть в SafeInvoke? Что-то с многопоточностью связанное?

Mikhail Sukhov
Mikhail Sukhov

Дмитрий: А можете релизацию этого интерфейса в объекте trader показать? Пусть даже сильно обрезанную. Чтобы все методы и событие интерфейса были описаны. Честно говоря, из этого кода по-прежнему не ясно, что делать.

Я правильно понял, что мой класс будет забирать данные из массива, и класть их в MySource.Trades именно в методе AddTrades? И какая специфика есть в SafeInvoke? Что-то с многопоточностью связанное?


namespace Ecng.Trading.Algo.Candles
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Threading;

	using Ecng.Collections;
	using Ecng.Common;
	using Ecng.Trading.BusinessEntities;

	/// <summary>
	/// Базовый источник тиковых сделок для <see cref="CandleManager"/>, получаемых через событие <see cref="ITrader.NewTrades"/>.
	/// </summary>
	public abstract class TraderCandleSource : Disposable, ICandleSource
	{
		private readonly int _maxTradeCount;
		private readonly int _maxCandleCount;
		private readonly SynchronizedList<Trade> _trades;
		private readonly SynchronizedDictionary<Candle, SynchronizedList<Trade>> _candleTrades;

		/// <summary>
		/// Инициализировать <see cref="TraderCandleSource"/>.
		/// </summary>
		/// <param name="trader">Торговый шлюз, у которого используется событие <see cref="ITrader.NewTrades"/>.</param>
		/// <param name="maxTradeCount">Максимальное количество сделок, которые нужно хранить.</param>
		/// <param name="maxCandleCount">Максимальное количество свечек, которые нужно хранить.</param>
		protected TraderCandleSource(ITrader trader, int maxTradeCount, int maxCandleCount)
		{
			if (trader == null)
				throw new ArgumentNullException("trader");

			this.Trader = trader;
			this.Trader.NewTrades += OnNewTrades;

			_maxTradeCount = maxTradeCount;
			_maxCandleCount = maxCandleCount;
			_trades = new SynchronizedList<Trade>(100000);
			_candleTrades = new SynchronizedDictionary<Candle, SynchronizedList<Trade>>(1000);
		}

		/// <summary>
		/// Шлюз к торговой системе.
		/// </summary>
		public ITrader Trader { get; private set; }

		/// <summary>
		/// Событие появления всех новых сделок.
		/// </summary>
		public event Action<IEnumerable<Trade>> NewTrades;

		/// <summary>
		/// Все накопленные сделки.
		/// </summary>
		public virtual IEnumerable<Trade> Trades
		{
			get { return _trades.SyncGet(c => c.ToArray()); }
		}

		/// <summary>
		/// Добавить сделку для свечки.
		/// </summary>
		/// <param name="candle">Свечка, для которой нужно добавить сделку.</param>
		/// <param name="trade">Новая сделка.</param>
		public void AddTrade(Candle candle, Trade trade)
		{
			_candleTrades.SafeAdd(candle).Add(trade);

			if (_candleTrades.Count > _maxCandleCount * 1.5)
			{
				_candleTrades.SyncDo(c =>
				{
					var elapsed = c.Skip(_maxCandleCount / 2).ToArray();
					c.Clear();
					c.AddRange(elapsed);
				});
			}
		}

		/// <summary>
		/// Получить все сделки по свечке.
		/// </summary>
		/// <param name="candle">Свечка, по которой нужно найти сделки.</param>
		/// <returns>Найденные сделки.</returns>
		public IEnumerable<Trade> GetTrades(Candle candle)
		{
			var trades = _candleTrades.TryGetValue(candle);
			return trades != null ? trades.SyncGet(c => c.ToArray()) : new Trade[0];
		}

		/// <summary>
		/// Обработчик события <see cref="ITrader.NewTrades"/>.
		/// </summary>
		/// <param name="trades">Новые сделки.</param>
		protected virtual void OnNewTrades(IEnumerable<Trade> trades)
		{
			_trades.AddRange(trades);

			if (_trades.Count > _maxTradeCount * 1.5)
			{
				_trades.SyncDo(c =>
				{
					var elapsed = c.Skip(_maxTradeCount / 2).ToArray();
					c.Clear();
					c.AddRange(elapsed);
				});
			}
		}

		/// <summary>
		/// Вызвать событие <see cref="NewTrades"/>.
		/// </summary>
		/// <param name="trades">Новые сделки.</param>
		protected void RaiseNewTrades(IEnumerable<Trade> trades)
		{
			this.NewTrades.SafeInvoke(trades);
		}

		/// <summary>
		/// Освободить занятые ресурсы.
		/// </summary>
		protected override void DisposeManaged()
		{
			this.Trader.NewTrades -= OnNewTrades;
			base.DisposeManaged();
		}
	}

	/// <summary>
	/// Источник тиковых сделок для <see cref="CandleManager"/>, получаемых через событие <see cref="ITrader.NewTrades"/>, 
	/// и отправляемый в <see cref="CandleManager"/> с определенным интервалом.
	/// </summary>
	public class ParallelTraderCandleSource : TraderCandleSource
	{
		private readonly SynchronizedList<Trade> _newTrades = new SynchronizedList<Trade>();

		private bool _isInProcess;
		private readonly Timer _timer;

		/// <summary>
		/// Создать <see cref="ParallelTraderCandleSource"/>.
		/// </summary>
		/// <param name="trader">Торговый шлюз, у которого используется событие <see cref="ITrader.NewTrades"/>.</param>
		public ParallelTraderCandleSource(ITrader trader)
			: this(trader, TimeSpan.FromMilliseconds(300))
		{
		}

		/// <summary>
		/// Создать <see cref="ParallelTraderCandleSource"/>.
		/// </summary>
		/// <param name="trader">Торговый шлюз, у которого используется событие <see cref="ITrader.NewTrades"/>.</param>
		/// <param name="interval">Интервал отправки новых сделок.</param>
		public ParallelTraderCandleSource(ITrader trader, TimeSpan interval)
			: base(trader, int.MaxValue, int.MaxValue)
		{
			if (trader == null)
				throw new ArgumentNullException("trader");

			_timer = interval.CreateTimer(OnProcessTrades);
		}

		/// <summary>
		/// Обработчик события <see cref="ITrader.NewTrades"/>.
		/// </summary>
		/// <param name="trades">Новые сделки.</param>
		protected override void OnNewTrades(IEnumerable<Trade> trades)
		{
			base.OnNewTrades(trades);

			_newTrades.AddRange(trades);
		}

		private void OnProcessTrades()
		{
			if (_isInProcess)
				return;

			_isInProcess = true;

			try
			{
				var newTrades = _newTrades.SyncGet(c =>
				{
					var retVal = c.ToArray();
					c.Clear();
					return retVal;
				});

				if (newTrades.Length > 0)
					base.RaiseNewTrades(newTrades);
			}
			finally
			{
				_isInProcess = false;
			}
		}

		/// <summary>
		/// Освободить занятые ресурсы.
		/// </summary>
		protected override void DisposeManaged()
		{
			_timer.Dispose();
			base.DisposeManaged();
		}
	}

	/// <summary>
	/// Источник тиковых сделок для <see cref="CandleManager"/>, получаемых через событие <see cref="ITrader.NewTrades"/>,
	/// и хранящий последние полученные сделки за определенный период.
	/// </summary>
	public class SyncTraderCandleSource : TraderCandleSource
	{
		/// <summary>
		/// Создать <see cref="SyncTraderCandleSource"/>.
		/// </summary>
		/// <param name="trader">Торговый шлюз, у которого используется событие <see cref="ITrader.NewTrades"/>.</param>
		public SyncTraderCandleSource(ITrader trader)
			: this(trader, 100000, 1000)
		{
		}

		/// <summary>
		/// Создать <see cref="SyncTraderCandleSource"/>.
		/// </summary>
		/// <param name="trader">Торговый шлюз, у которого используется событие <see cref="ITrader.NewTrades"/>.</param>
		/// <param name="maxTradeCount">Максимальное количество сделок, которые нужно хранить.</param>
		/// <param name="maxCandleCount">Максимальное количество свечек, которые нужно хранить.</param>
		public SyncTraderCandleSource(ITrader trader, int maxTradeCount, int maxCandleCount)
			: base(trader, maxTradeCount, maxCandleCount)
		{
		}

		/// <summary>
		/// Обработчик события <see cref="ITrader.NewTrades"/>.
		/// </summary>
		/// <param name="trades">Новые сделки.</param>
		protected override void OnNewTrades(IEnumerable<Trade> trades)
		{
			base.OnNewTrades(trades);
			base.RaiseNewTrades(trades);
		}
	}
}

Дмитрий
Дмитрий Autor

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