protected override PriceCalculationRow[] GetMaximumVolumeRows(PriceCalculationRow[] table)
        {
            decimal maxVolume = 0;

              foreach (PriceCalculationRow row in table)
              {
            row.TradeableQuantity = Math.Min(row.AggregateBuyQuantity, row.AggregateSellQuantity);
            if (row.TradeableVolume > maxVolume)
              maxVolume = row.TradeableVolume;
              }

              return table.Where(r => r.TradeableVolume == maxVolume).ToArray();
        }
        protected override PriceCalculationRow[] GetMinimumOrderImbalanceRows(PriceCalculationRow[] table)
        {
            decimal minImbalance = decimal.MaxValue;

              foreach (PriceCalculationRow row in table)
              {
            row.NormalOrderImbalance = Math.Abs(row.AggregateBuyQuantity - row.AggregateSellQuantity) * row.Price;
            if (row.NormalOrderImbalance < minImbalance)
              minImbalance = row.NormalOrderImbalance;
              }

              return table.Where(r => r.NormalOrderImbalance == minImbalance).ToArray();
        }
        protected override PriceCalculationRow[] GetMaximumQuantityRows(PriceCalculationRow[] table)
        {
            int maxQuantity = 0;

              foreach (PriceCalculationRow row in table)
              {
            row.TradeableQuantity = Math.Min(row.AggregateBuyQuantity, row.AggregateSellQuantity);
            if (row.TradeableQuantity > maxQuantity)
              maxQuantity = row.TradeableQuantity;
              }

              return table.Where(r => r.TradeableQuantity == maxQuantity).ToArray();
        }
Esempio n. 4
0
        /// <summary>
        /// První kritérium pro výpočet ceny. Pro všechny ceny v tabulce spočítá objem, který by za 
        /// danou cenu mohl být zobchodován, a vybere cenu, pro niž je zobchodovatelný objem největší.
        /// Pokud je taková cena jedinečná, vrátí ji jako výsledek, v opačném případě předá vhodné 
        /// kandidáty metodě <code>GetPriceByNormalOrderImbalance</code> hodnotící druhé kritérium.
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private decimal GetPriceByMaximumTradeableVolume(PriceCalculationRow[] table)
        {
            PriceCalculationRow[] maxVolumeRows = GetMaximumVolumeRows(table);

              if (Debug)
              {
            Recorder.Instance.WriteLine("\r\nChecking MaximumTradeableVolume Criterion...");
            Recorder.Instance.Print(table);
              }

              switch (maxVolumeRows.Length)
              {
            case 0: throw new NullReferenceException("maxVolumeRows.Length == 0");
            case 1: return maxVolumeRows[0].Price;
            default: return GetPriceByNormalOrderImbalance(maxVolumeRows);
              }
        }
Esempio n. 5
0
        /// <summary>
        /// Čtvrté a páté kritérium pro výpočet ceny. Spočítá průmernou cenu ze (sub)tabulky; pokud je 
        /// násobkem základní jednotky tickSize, vrátí ji jako výsledek.
        /// V opačném případě se rozhoduje podle předchozí ceny: pokud byla vyšší než nyní spočítaná
        /// průměrná cena, zaokrouhlí se průměrná cena na nejbližší základní jednotku směrem nahoru, 
        /// v opačném případě směrem dolů.
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private decimal GetPriceByAverage(PriceCalculationRow[] table)
        {
            if (Debug)
              {
            Recorder.Instance.WriteLine("\r\nChecking Average Criterion...");
            Recorder.Instance.Print(table);
              }

              decimal averagePrice = table.Average(r => r.Price);

              if (averagePrice % tickSize == 0)
            return averagePrice;

              if (lastPrice > averagePrice)
            return tickSize * Math.Ceiling(averagePrice / tickSize);

              return tickSize * Math.Floor(averagePrice / tickSize);
        }
        /// <summary>
        /// Vloží do tabulky <code>table</code> objednávky na prodej seřazené VZESTUPNĚ.
        /// Tato metoda může být volána po vložení objednávek na nákup.
        /// Výsledkem je sestupně seřazená tabulka podle ceny.
        /// </summary>
        /// <param name="sellList">Seznam objednávek na prodej.</param>
        /// <param name="table">Tabulka, do které mají být objednávky vloženy.</param>
        private void InsertSellOrders(Order[] sellList, IList <PriceCalculationRow> table)
        {
            int rowIndex = table.Count - 1;
            PriceCalculationRow lastRow       = table[rowIndex];
            int aggregatePreviousRowsQuantity = 0;

            foreach (Order sellOrder in sellList)
            {
                decimal price  = sellOrder.ProposedPrice;
                int     amount = sellOrder.Amount;

                /// Zapsani prodejniho mnozstvi, posun v tabulce nahoru (tj. k vyssi cene)
                while (lastRow.Price < price && rowIndex > 0)
                {
                    lastRow.AggregateSellQuantity = aggregatePreviousRowsQuantity;

                    rowIndex--;
                    lastRow = table[rowIndex];
                }

                /// Narazili jsme na cenu, ktera nebyla obsazena v "buy" tabulce, musi se vlozit
                if (lastRow.Price > price)
                {
                    PriceCalculationRow newRow = new PriceCalculationRow(price);
                    newRow.AggregateBuyQuantity = lastRow.AggregateBuyQuantity; // nakup jako za vyssi cenu
                    rowIndex++;                                                 // posunem se o krok zpatky, niz v tabulce
                    lastRow = newRow;
                    table.Insert(rowIndex, newRow);
                }

                /// Cenu jsme v tabulce nasli, nebo ji vlozili. V kazdem pripade pro ni zvysime mnozstvi.
                /// Zapis mnozstvi probehne v cyklu posunu po tabulce
                aggregatePreviousRowsQuantity += amount;
            }

            /// Na zaver vyplnime mnozstvi pro vsechny zbyvajiji nejvyssi ceny z "buy" tabulky
            for (int index = 0; index <= rowIndex; index++)
            {
                table[index].AggregateSellQuantity = aggregatePreviousRowsQuantity;
            }
        }
        /// <summary>
        /// Vloží do (prázdné) tabulky <code>table</code> objednávky na nákup seřazené SESTUPNĚ.
        /// Tato metoda musí být volána před vložením objednávek na prodej!
        /// </summary>
        /// <param name="buyList">Seznam objednávek na nákup.</param>
        /// <param name="table">Tabulka, do které mají být objednávky vloženy.</param>
        private void InsertBuyOrders(Order[] buyList, IList <PriceCalculationRow> table)
        {
            PriceCalculationRow previousRow   = null;
            int aggregatePreviousRowsQuantity = 0;

            foreach (Order buyOrder in buyList)
            {
                decimal price  = buyOrder.ProposedPrice;
                int     amount = buyOrder.Amount;

                if (previousRow == null || previousRow.Price != price) // vkladame novou cenu
                {
                    PriceCalculationRow row = new PriceCalculationRow(price);
                    row.AggregateBuyQuantity = amount + aggregatePreviousRowsQuantity;
                    table.Add(row);
                    previousRow = row;
                }
                else // takova cena uz existuje
                {
                    previousRow.AggregateBuyQuantity += amount;
                }
                aggregatePreviousRowsQuantity = previousRow.AggregateBuyQuantity;
            }
        }
        /// <summary>
        /// Vloží do (prázdné) tabulky <code>table</code> objednávky na nákup seřazené SESTUPNĚ. 
        /// Tato metoda musí být volána před vložením objednávek na prodej!
        /// </summary>
        /// <param name="buyList">Seznam objednávek na nákup.</param>
        /// <param name="table">Tabulka, do které mají být objednávky vloženy.</param>
        private void InsertBuyOrders(Order[] buyList, IList<PriceCalculationRow> table)
        {
            PriceCalculationRow previousRow = null;
              int aggregatePreviousRowsQuantity = 0;

              foreach (Order buyOrder in buyList)
              {
            decimal price = buyOrder.ProposedPrice;
            int amount = buyOrder.Amount;

            if (previousRow == null || previousRow.Price != price) // vkladame novou cenu
            {
              PriceCalculationRow row = new PriceCalculationRow(price);
              row.AggregateBuyQuantity = amount + aggregatePreviousRowsQuantity;
              table.Add(row);
              previousRow = row;
            }
            else // takova cena uz existuje
            {
              previousRow.AggregateBuyQuantity += amount;
            }
            aggregatePreviousRowsQuantity = previousRow.AggregateBuyQuantity;
              }
        }
        /// <summary>
        /// Vloží do tabulky <code>table</code> objednávky na prodej seřazené VZESTUPNĚ. 
        /// Tato metoda může být volána po vložení objednávek na nákup.
        /// Výsledkem je sestupně seřazená tabulka podle ceny.
        /// </summary>
        /// <param name="sellList">Seznam objednávek na prodej.</param>
        /// <param name="table">Tabulka, do které mají být objednávky vloženy.</param>
        private void InsertSellOrders(Order[] sellList, IList<PriceCalculationRow> table)
        {
            int rowIndex = table.Count - 1;
              PriceCalculationRow lastRow = table[rowIndex];
              int aggregatePreviousRowsQuantity = 0;

              foreach (Order sellOrder in sellList)
              {
            decimal price = sellOrder.ProposedPrice;
            int amount = sellOrder.Amount;

            /// Zapsani prodejniho mnozstvi, posun v tabulce nahoru (tj. k vyssi cene)
            while (lastRow.Price < price && rowIndex > 0)
            {
              lastRow.AggregateSellQuantity = aggregatePreviousRowsQuantity;

              rowIndex--;
              lastRow = table[rowIndex];
            }

            /// Narazili jsme na cenu, ktera nebyla obsazena v "buy" tabulce, musi se vlozit
            if (lastRow.Price > price)
            {
              PriceCalculationRow newRow = new PriceCalculationRow(price);
              newRow.AggregateBuyQuantity = lastRow.AggregateBuyQuantity; // nakup jako za vyssi cenu
              rowIndex++; // posunem se o krok zpatky, niz v tabulce
              lastRow = newRow;
              table.Insert(rowIndex, newRow);
            }

            /// Cenu jsme v tabulce nasli, nebo ji vlozili. V kazdem pripade pro ni zvysime mnozstvi.
            /// Zapis mnozstvi probehne v cyklu posunu po tabulce
            aggregatePreviousRowsQuantity += amount;
              }

              /// Na zaver vyplnime mnozstvi pro vsechny zbyvajiji nejvyssi ceny z "buy" tabulky
              for (int index = 0; index <= rowIndex; index++)
              {
            table[index].AggregateSellQuantity = aggregatePreviousRowsQuantity;
              }
        }
Esempio n. 10
0
 protected abstract PriceCalculationRow[] GetMinimumOrderImbalanceRows(PriceCalculationRow[] table);
Esempio n. 11
0
 protected abstract PriceCalculationRow[] GetMaximumVolumeRows(PriceCalculationRow[] table);
Esempio n. 12
0
 protected abstract PriceCalculationRow[] GetMaximumQuantityRows(PriceCalculationRow[] table);
Esempio n. 13
0
        /// <summary>
        /// Třetí kritérium pro výpočet ceny. Pro všechny ceny v (sub)tabulce zkontroluje, zda převažuje
        /// nabídka nad poptávkou, nebo naopak. Pokud ve všech případech převažuje poptávka, vybere 
        /// z možných cen největší. Pokud ve všech případech převažuje nabídka, vybere nejnižší cenu.
        /// Ve zbývajících případech (TEMP!) spočítá cenu jako průměr ze zvažovaných cen.
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private decimal GetPriceByOrderImbalanceDirection(PriceCalculationRow[] table)
        {
            if (Debug)
              {
            Recorder.Instance.WriteLine("\r\nChecking OrderImbalanceDirection Criterion...");
            Recorder.Instance.Print(table);
              }

              if (table.All(r => r.AggregateBuyQuantity > r.AggregateSellQuantity))
            return table.Max(r => r.Price);

              if (table.All(r => r.AggregateBuyQuantity < r.AggregateSellQuantity))
            return table.Min(r => r.Price);

              return GetPriceByAverage(table);
        }
Esempio n. 14
0
        /// <summary>
        /// Druhé kritérium pro výpočet ceny. Pro všechny ceny v (sub)tabulce spočítá nezobchodovatelný
        /// objem odpovídající dané ceně, a vybere cenu, pro niž je tato hodnota nejmenší.
        /// Pokud je taková cena jedinečná, vrátí ji jako výsledek, v opačném případě předá vhodné 
        /// kandidáty metodě <code>GetPriceByOrderImbalanceDirection</code> hodnotící třetí kritérium.
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private decimal GetPriceByNormalOrderImbalance(PriceCalculationRow[] table)
        {
            PriceCalculationRow[] minImbalanceRows = GetMinimumOrderImbalanceRows(table);

              if (Debug)
              {
            Recorder.Instance.WriteLine("\r\nChecking NormalOrderImbalance Criterion...");
            Recorder.Instance.Print(table);
              }

              switch (minImbalanceRows.Length)
              {
            case 0: throw new NullReferenceException("minImbalanceRows.Length == 0");
            case 1: return minImbalanceRows[0].Price;
            default: return GetPriceByOrderImbalanceDirection(minImbalanceRows);
              }
        }