Реализация переливщика валют для Бинанса

Собственно сабж

  1. karuzzo

    Регистрация:
    16.08.19
    Сообщения:
    99
    Был на сайте:
    05.01.23

    На равне с прочими интересными стратегиями я решил реализовать переливщика валют каку автора самой системы, так как он не сильно отличается по устройству от моего прошлого робота торгующего портфелями валют, хоть и несколько сложнее так как есть рекурсивная функция обхода всех возможных сделок по каждой валюте и структура последовательности, которые я выложу ниже для того чтоб вам было проще и интереснее пробовать разрабатывать роботов аналогичных роботам автора терминала, а возможно нам Алексей что то подскажет.

    Для начала нужно подписаться на все валюты бинанса и по событию нового стакана распихивать данные в лист или словарь, что быстрее не проверял вероятнее лист, но удобнее словарь так как есть возможность обращаться к данным по имени инструмента без цикла, и его скорости достаточно. Выглядит это примерно так:

    private void ServerMaster_NewMarketDepthEvent(MarketDepth marketDepth)
            {
                if (!depthsDictionary.ContainsKey(marketDepth.SecurityNameCode))
                {
                    depthsDictionary.Add(marketDepth.SecurityNameCode, marketDepth);
                }
                else
                {
                    depthsDictionary.Remove(marketDepth.SecurityNameCode);
                    depthsDictionary.Add(marketDepth.SecurityNameCode, marketDepth);
                }
            }

    Теперь когда у нас есть стаканы всех валют нужно рекурсивно перемножить их структуры взаимодействия для этого создадим саму структуру  ниже привожу примерный код, без расчета комиссии, но вы можете ее посчитать :

        public struct Deal

        {

            public decimal EnterValue;

            public decimal ExitValue;

            public string Name;

            public string MasterCurrency;

            public string ExitCurrency;

            public string SlaveCurrency;

            public decimal Comission;

            public decimal Ask;

            public decimal Bid;

            public string Path;

            public decimal SellValue()

            {

                return EnterValue * Bid - Math.Abs(Ask - Bid);

            }

            public decimal BuyValue()

            {

                return EnterValue / Ask - Math.Abs(Ask - Bid);

            }

        }

    Не смотря на то, что структура все же легче класса, в данной структуре есть математика и мы все же не успеем перемножить все структуры между приемом новых стаканов, как ограничить количество вычислений результата решать вам, это может быть ограничение по времени или для самых искушенных может быть создан класс с остальной логикой где вычисления будут на каждое событие стакана и вычисляться будет в паралельных потоках, а рекурсия вызывает себя и передает в себя результат вычислений, где X - количество итераций (длинна цепочки 3-4-5-6 и тд.) и может выглядеть так:

     private List<Deal> GetAllDeal(List<Deal> enterSequence, List<Deal> baseSequence, int x)

            {

                List<Deal> exitSequence = new List<Deal>();

                if (x <= 1)

                    return enterSequence;

                else

                {

                    if (enterSequence == null)

                    {

                        for (int i = 0; i < baseSequence.Count; i++)

                        {

                            if (myPortfolioName.ValueString == baseSequence[i].MasterCurrency)

                            {

                                var deal = baseSequence[i];

                                deal.EnterValue = myPortfolio.ValueCurrent;

                                deal.Path = deal.Name;

                                deal.ExitCurrency = deal.SlaveCurrency;

                                deal.ExitValue = deal.SellValue();

                                exitSequence.Add(deal);

                            }

                        }

                    }

                    else

                    {                  

                        for (int i = 0; i < enterSequence.Count; i++)

                        {

                            for (int a = 0; a < baseSequence.Count; a++)

                            {

                                if (enterSequence[i].ExitCurrency == baseSequence[a].MasterCurrency)

                                {

                                    var deal = baseSequence[a];

                                    deal.EnterValue = enterSequence[i].ExitValue;

                                    deal.Path = enterSequence[i].Path + " - " + deal.Name;

                                    deal.ExitCurrency = deal.SlaveCurrency;

                                    deal.ExitValue = deal.SellValue();

                                    exitSequence.Add(deal);

                                }

     

                                if (enterSequence[i].ExitCurrency == baseSequence[a].SlaveCurrency)

                                {

                                    var deal = baseSequence[a];

                                    deal.EnterValue = enterSequence[i].ExitValue;

                                    deal.Path = enterSequence[i].Path + " - !" + deal.Name;

                                    deal.ExitCurrency = deal.MasterCurrency;

                                    deal.ExitValue = deal.BuyValue();

                                    exitSequence.Add(deal);

                                }

                            }

                        }

                    }

                    return GetAllDeal(exitSequence, baseSequence, x - 1);

                }

            }

    Она реализована по-старинке, но кто хочет юзать новый функционал языка можете попробовать использовать кортежи. После завершения вычислений отфильтруем убыточные цепочки структур:

    foreach (var dealOut in dealsOut)

                {

                    if (dealOut.ExitCurrency == myPortfolioName.ValueString)

                    {

                        decimal bestPer = (dealOut.ExitValue - balance) * 100 / balance;

                        if (bestPer > Diff.ValueDecimal)

                            exitDealOut.Add(dealOut);

                    }

                }

    Теперь когда у нас на руках есть все возможные комбинации прибыльных переливов отправляем самую прибыльную цепочку на выполнение, path структуры и есть искомая последовательность.

    Copyrigth - используя части представленного кода, вы недолжны использовать нижнее подчеркивание в именах приватных членах. Пример:

    a = _a; так как это рудимент не рекомендовынный микрософтом, а так же плохой тон и просто я это не люблю))

    karuzzo
    04.12.2019 12:17
    #1