I decided to use Extension Methods in my new cryptocurrency trading application
Tags: csharp, coding, cryptocurrency
Published: 2022-08-09 20:12:00

Hi, this is a really short post. I wouldn't call it an epiphany, but I decided to use extension methods to add filtering and business logic to my application. Of course I use extension methods, but it isn't about them per se.

Before going any further - this is not a high frequency trading application (HFT). I won't need to care about performance in the typical way we think of automated trading but I am certain .Net Core and clever data modelling will save the day.

I have been into cryptocurrency for 5 years plus - too short tbf, but in that time I have come up with a very simple trading strategy. Don't worry, am not intending to sell some scam on here (or anywhere). However, I know I can improve my manual trading strategy using my programming skills. After all, I have worked in finance on countless projects at a high level within the financial space. 

Part of the reason many financial people aren't involved in cryptocurrency is because it is still a taboo topic.

You can read a high-level overview of what I am looking into here. 

https://www.inforhino.co.uk/article/Discussion/Insights%20and%20Thoughts/Automated-Cryptocurrency-Trading-Engine-in-dotnet----08-Aug-2022

Normally, I would have created various classes, injected them in. One cool thing you can do is to create an IList<ILogicTest> and add a series of logic tests, configuring which test you wish to perform - for example.

```csharp
IList<ILogicTest> logicTests = new List<ILogicTest>()
{{new ShouldTrade()},{new ShouldNeverTrade()},{new BuyLikeYouNeedANewHandbag()}};
```

Now, my application will still do something like the above in certain parts. This is a great way to avoid breaking the single responsibility principle. I have written about this before. However, how many ShouldTrade classes will we ever need? Some will say, but perhaps we want a different implementation - well why not create those different implementations but encapsulate the use of the extension method within there?

People will say - who cares? Many don't like Extension Methods - certainly we get collisions within the same namespaces, we can't inject in, but for pure evaluation on primitive types - why not?

I think that what I am trying to achieve is a little more clarity and less clutter. I don't know if this will work, but it is worth a try if it helps make the codebase simpler.

There are those claiming we can't unit test extension methods of course - of course we can.

### for those that want to see a bit of C# 
If you find any bugs - please let me know. I can think of lots of issues, but without further ado.

```csharp
namespace IR.AssetTrader.Analyser.Helpers
{
    public static class AssetPairRateHelper
    {

        static public IEnumerable<AssetPairRate> GetAssetPairRatesByAsset(this IEnumerable<AssetPairRate> assetPairRates, string CodeLong, string CodeShort)
        {
            return assetPairRates.Where(x => x.LongAsset.Code == CodeLong && x.ShortAsset.Code == CodeShort);

        }


        static public IEnumerable<AssetPairRate> GetAssetPairRatesByAssetDate(this IEnumerable<AssetPairRate>  assetPairRates, string CodeLong, string CodeShort, DateTime Start,DateTime End )
        {
            return assetPairRates.Where(x => x.LongAsset.Code == CodeLong && x.ShortAsset.Code == CodeShort && x.EventTMS >= Start && 
            x.EventTMS <= End);

        }
        static public IEnumerable<AssetPairRate> GetAssetPairRatesByAsset(this IEnumerable<AssetPairRate> assetPairRates, AssetPair assetPair)
        {
            return assetPairRates.Where(x => x.LongAsset.Code == assetPair.LongAsset.Code && x.ShortAsset.Code == assetPair.ShortAsset.Code );

        }
        static public IEnumerable<AssetPairRate> GetAssetPairRatesByAssetDate(this IEnumerable<AssetPairRate> assetPairRates, AssetPair assetPair, DateTime Start, DateTime End)
        {
            return assetPairRates.Where(x => x.LongAsset.Code == assetPair.LongAsset.Code && x.ShortAsset.Code == assetPair.ShortAsset.Code && x.EventTMS >= Start &&
            x.EventTMS <= End);

        }
        static public AssetPair GetAssetPairFromAssetPairRates(this IEnumerable<AssetPairRate> assetPairRates, AssetPair assetPair)
        {

            var firstAsset = assetPairRates.Where(x => x.LongAsset.Code == assetPair.LongAsset.Code && x.ShortAsset.Code == assetPair.ShortAsset.Code).First();

            return new AssetPair { LongAsset = firstAsset.LongAsset, ShortAsset = firstAsset.ShortAsset };

        }
        static public AssetPair GetAssetPairFromAssetPairRates(this IEnumerable<AssetPairRate> assetPairRates, string CodeLong, string CodeShort)
        {
            var firstAsset = assetPairRates.Where(x => x.LongAsset.Code == CodeLong && x.ShortAsset.Code == CodeShort).First();

            return new AssetPair { LongAsset = firstAsset.LongAsset, ShortAsset = firstAsset.ShortAsset };


        }
    }
}

```