3
\$\begingroup\$

My task is to compute average half spread in percentages on a stream of market. This is part of the coding assignment that I have received.

namespace CodingAssignment
{
    public interface IMarketDataFeed
    {
        string StockName { get; }
        event Action<MarketDataUpdate> Update;
    }

    public interface IIndicator
    {
        event Action<double> IndicatorUpdate;
    }

    /// <summary>
    /// Computes the average half spread (ie bid to mid) in percentage on a stream of market data updates
    /// </summary>

    public class AverageHalfSpreadIndicator
    {
        private List<MarketDataUpdate> _lastUpdates;

        public AverageHalfSpreadIndicator(IMarketDataFeed marketDataFeed)
        {          
            marketDataFeed.Update += OnMarketDataUpdate;
        }

        private void OnMarketDataUpdate(MarketDataUpdate updates)
        {
            _lastUpdates.Add(updates);           
            if (_lastUpdates.Count == 20)           
            {               
                _lastUpdates.RemoveAt(0);           
            }

            var start = DateTime.Now;           
            var spreads = _lastUpdates.Select(x => 100 * (x.Mid - x.Bid) / x.Bid);           
            Console.WriteLine("Time to compute spreads: "+(DateTime.Now - start).TotalMilliseconds+" ms");   

            var averageSpread = spreads.Average();           
            Console.WriteLine("Total time:" + (DateTime.Now - start).TotalMilliseconds + " ms");

            IndicatorUpdate(averageSpread);
        }

        public event Action<double> IndicatorUpdate;
    }

    public class MarketDataUpdate
    {
        public double Bid { get; set; }
        public double Ask { get; set; }
        public double Last { get; set; }

        public double Mid
        {           
            get { return (Bid + Ask) / 2; }

        }
    }
}

C# is a fairly new language for me, so there might be some best practises that I may have missed. I am also wondering how this would behave in a multi-threaded environment.

\$\endgroup\$
5
\$\begingroup\$

Your AverageHalfSpreadIndicator doesn't implement IIndicator. I think you just forgot to

public class AverageHalfSpreadIndicator : IIndicator

You should instantiate your _lastUpdates:

public AverageHalfSpreadIndicator(IMarketDataFeed marketDataFeed)
{
    _lastUpdates = new List<MarketDataUpdate>();
    marketDataFeed.Update += OnMarketDataUpdate;
}

I don't like this code:

_lastUpdates.Add(updates);
if (_lastUpdates.Count == 20)
{
    _lastUpdates.RemoveAt(0);
}

I mean, it's fine, but I'd prefer to implement the _lastUpdates as a fixed sized queue. You can find many implementations on SO, for example: 1, 2, 3.

Also, your code is not thread-safe. If your code'd be called by many threads it'd break.

Don't use DateTime to measure execution time. There is a special class for this task: System.Diagnostics.Stopwatch.

var stopWatch = new Stopwatch();
stopWatch.Start();
var spreads = _lastUpdates.Select(x => 100 * (x.Mid - x.Bid) / x.Bid);
Console.WriteLine("Time to compute spreads: " + stopWatch.ElapsedMilliseconds + " ms");

var averageSpread = spreads.Average();
Console.WriteLine("Total time:" + stopWatch.ElapsedMilliseconds + " ms");
stopWatch.Stop();

This is not a big deal, but instead of encapsulating just Mid you can encapsulate whole 100 * (x.Mid - x.Bid) / x.Bidin your MarketDataUpdate.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.