//This class now stores the information need for the stance and is called every turn to check it vs its conditions for success and failure
            public MarketStance(Stance s, int Quanity, int ClientID, string TargetStock, AlgoTrader owner, ThreadDataBaseHandler threadDataBaseHandler)
            {
                this.threadDataBaseHandler = threadDataBaseHandler;
                stance           = s;
                Owner            = owner;
                client           = ClientID;
                this.TargetStock = TargetStock;
                StartTime        = DateTime.Now;
                double CurrentPrice = threadDataBaseHandler.GetCountDouble("SELECT SUM(CurrentPrice) FROM Stock WHERE StockName = '" + this.TargetStock + "'");

                CurrentPrice = Math.Round(CurrentPrice, 2);
                switch (stance)
                {
                case Stance.ShortTermLong:
                    //For a long the trader believes the market will go up so success price if above current price
                    this.Quanity = Quanity;
                    SuccessPrice = CurrentPrice + 0.02f;
                    FailurePrice = CurrentPrice - 0.01f;
                    RequiredTime = 5;
                    ShortTermLong(Quanity, CurrentPrice);
                    break;

                case Stance.ShortTermShort:
                    //For a short the trader believes the market will go doen so success price if below current price
                    this.Quanity = Quanity;
                    SuccessPrice = CurrentPrice - 0.02f;
                    FailurePrice = CurrentPrice + 0.01f;
                    RequiredTime = 5;
                    ShortTermShort(Quanity, CurrentPrice);
                    break;
                }
                //Close DB thread for other parts of the program to be free to connect to DB
                threadDataBaseHandler.CloseCon();
            }
        public static void RunTicker(bool PriceHistoryCleaner)
        {
            if (PriceHistoryCleaner)
            {
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ": Pricing Cleaned");
            }
            //If this is a new day we need to update the daily varaibles in the DB which are used to calculate daily movements of the stocks
            if (DateTime.Now.Day != LastDay)
            {
                LastDay = DateTime.Now.Day;
                DataBaseHandler.SetData("UPDATE Stock SET OpeningPriceToday = CurrentPrice, HighToday = CurrentPrice, LowToday = CurrentPrice, VolumeTraded = 0");
            }
            //Grab all the stocks from the DB
            List <Stock>    stocks = new List <Stock>();
            MySqlDataReader reader = DataBaseHandler.GetData("SELECT StockName, CurrentPrice FROM Stock");

            while (reader.Read())
            {
                stocks.Add(new Stock((string)reader["StockName"], (double)reader["CurrentPrice"]));
            }
            int i = 0;

            foreach (Stock s in stocks)
            {
                //Make sure we have anough ThreadDataBaseHandlers for each of the stocks
                while (i > DataBaseHandlers.Count - 1)
                {
                    DataBaseHandlers.Add(new ThreadDataBaseHandler());
                }
                //Get the total number of bids added to the pool since last turn for this stock
                int NumberOfBids = DataBaseHandler.GetCount("SELECT SUM(Quantity) FROM Pool WHERE Type = 0 AND StockName = '" + s.StockName + "'  AND TurnsInPool = 0");
                //Get the total number of offers added to the pool since last turn for this stock
                int NumberOfOffers = DataBaseHandler.GetCount("SELECT SUM(Quantity) FROM Pool WHERE Type = 1 AND StockName = '" + s.StockName + "'  AND TurnsInPool = 0");
                //Get the total number of stocks in circulation for this stock
                long   StocksInCirculation = DataBaseHandler.GetCount("SELECT SUM(Quantity) FROM Inventories WHERE StockName = '" + s.StockName + "'");
                double NewPrice            = UpdateStockPrice(s.StockName, s.StartingPrice, NumberOfBids, NumberOfOffers, StocksInCirculation);
                //Check if price has changed, if not there is no need to send the information to the DB
                if (NewPrice != s.StartingPrice)
                {
                    DataBaseHandler.SetData("UPDATE Stock SET CurrentPrice = " + NewPrice + " WHERE StockName = '" + s.StockName + "'");
                }
                //Update daily movements variables
                DataBaseHandler.SetData("UPDATE Stock SET LowToday = CurrentPrice WHERE CurrentPrice < LowToday");
                DataBaseHandler.SetData("UPDATE Stock SET HighToday = CurrentPrice WHERE CurrentPrice > HighToday");
                //Insert the price into the PricingHistory for the graphs the users can see in the trading application
                DataBaseHandler.SetData("INSERT INTO PricingHistory (Price, StockName) VALUES (" + NewPrice + ", '" + s.StockName + "')");
                if (PriceHistoryCleaner)
                {
                    //PricingThinner reduces the frequency of data for a stock the older the data is in order to keep the DB at a reasonable size
                    //Grab an instance of the threadDataBaseHandler
                    ThreadDataBaseHandler threadDataBaseHandler = DataBaseHandlers[i];
                    //Pass the this Task.Factory to be assign a thread
                    Task.Factory.StartNew(() => PricingThinner(s.StockName, threadDataBaseHandler));
                    //Restart the timmer for Timing Manager
                    TimingManager.PricingTimer.Restart();
                }
                i++;
            }
        }
        public static void RemoveFromPool(BidsAndOffers Trade, ThreadDataBaseHandler threadDataBaseHandler)
        {
            //When a bid or offer is ready to be removed it passed to this method which removes it from DB
            string command = string.Format("DELETE FROM Pool WHERE Type = {0} AND TimePlaced = '{1}' AND Price = {2} AND User = {3} AND StockName = '{4}'", Trade.Type, Trade.TimePlaced.ToString("yyyy-MM-dd HH:mm:ss"), Trade.Price, Trade.User, Trade.StockName);

            threadDataBaseHandler.SetData(command);
            threadDataBaseHandler.CloseCon();
        }
        /// <summary>
        /// Reduces the frequency of data for a stock the older the data is in order to keep the DB at a reasonable size
        /// </summary>
        static void PricingThinner(string StockName, ThreadDataBaseHandler threadDataBaseHandler)
        {
            MySqlDataReader reader      = threadDataBaseHandler.GetData(string.Format("SELECT Time From PricingHistory WHERE StockName = '{0}' AND Time < '{1}' ORDER BY Time ASC", StockName, DateTime.Now.AddSeconds(-10).ToString("yyyy-MM-dd HH:mm:ss")));
            List <DateTime> LastHour    = new List <DateTime>();
            List <DateTime> Last12Hours = new List <DateTime>();
            List <DateTime> LastDay     = new List <DateTime>();
            List <DateTime> LastWeek    = new List <DateTime>();
            List <DateTime> LastMonth   = new List <DateTime>();
            List <DateTime> Longer      = new List <DateTime>();

            while (reader.Read())
            {
                DateTime time = (DateTime)reader["Time"];
                if (time > DateTime.Now.AddHours(-1))
                {
                    LastHour.Add(time);
                }
                else if (time > DateTime.Now.AddHours(-12))
                {
                    Last12Hours.Add(time);
                }
                else if (time > DateTime.Now.AddDays(-1))
                {
                    LastDay.Add(time);
                }
                else if (time > DateTime.Now.AddDays(-7))
                {
                    LastWeek.Add(time);
                }
                else if (time > DateTime.Now.AddMonths(-1))
                {
                    LastMonth.Add(time);
                }
                else
                {
                    Longer.Add(time);
                }
            }
            //For each time period there is a set gap which entries need to be apart by.
            //If the gap is not the right size then the entry is removed from the DB
            List <DateTime> ToBeDeleted = new List <DateTime>();
            DateTime        last        = DateTime.MinValue;

            for (int i = 0; i < LastHour.Count; i++)
            {
                if (i == 0)
                {
                    last = LastHour[i];
                    continue;
                }
                if ((LastHour[i] - last).Seconds < 10)
                {
                    ToBeDeleted.Add(LastHour[i]);
                }
                else
                {
                    last = LastHour[i];
                }
            }
            last = DateTime.MinValue;
            for (int i = 0; i < Last12Hours.Count; i++)
            {
                if (i == 0)
                {
                    last = Last12Hours[i];
                    continue;
                }
                if ((Last12Hours[i] - last).Minutes < 2)
                {
                    ToBeDeleted.Add(Last12Hours[i]);
                }
                else
                {
                    last = Last12Hours[i];
                }
            }
            last = DateTime.MinValue;
            for (int i = 0; i < LastDay.Count; i++)
            {
                if (i == 0)
                {
                    last = LastDay[i];
                    continue;
                }
                if ((LastDay[i] - last).Minutes < 10)
                {
                    ToBeDeleted.Add(LastDay[i]);
                }
                else
                {
                    last = LastDay[i];
                }
            }
            last = DateTime.MinValue;
            for (int i = 0; i < LastWeek.Count; i++)
            {
                if (i == 0)
                {
                    last = LastWeek[i];
                    continue;
                }
                if ((LastWeek[i] - last).Hours < 1)
                {
                    ToBeDeleted.Add(LastWeek[i]);
                }
                else
                {
                    last = LastWeek[i];
                }
            }
            last = DateTime.MinValue;
            for (int i = 0; i < LastMonth.Count; i++)
            {
                if (i == 0)
                {
                    last = LastMonth[i];
                    continue;
                }
                if ((LastMonth[i] - last).Hours < 6)
                {
                    ToBeDeleted.Add(LastMonth[i]);
                }
                else
                {
                    last = LastMonth[i];
                }
            }
            last = DateTime.MinValue;
            for (int i = 0; i < Longer.Count; i++)
            {
                if (i == 0)
                {
                    last = Longer[i];
                    continue;
                }
                if ((Longer[i] - last).Days < 7)
                {
                    ToBeDeleted.Add(Longer[i]);
                }
                else
                {
                    last = Longer[i];
                }
            }
            for (int i = 0; i < ToBeDeleted.Count; i++)
            {
                threadDataBaseHandler.SetData("DELETE FROM PricingHistory WHERE StockName = '" + StockName + "' AND Time = '" + ToBeDeleted[i].ToString("yyyy-MM-dd HH:mm:ss") + "'");
            }
        }
        public static void CreateTrade(ref BidsAndOffers Bid, ref BidsAndOffers Offer, int Quantity, ThreadDataBaseHandler threadDataBaseHandler)
        {
            //Get the total quantity that the user can sell
            int StockAvailable = threadDataBaseHandler.GetCount(string.Format("SELECT COUNT(Quantity) FROM Inventories WHERE StockName = '{0}' AND UserID = {1}", Offer.StockName, Offer.User));

            if (Quantity > StockAvailable)
            {
                //If the quantity if the sale is greater than that the user can offer limit to the max amount the user could sell
                Quantity = StockAvailable;
            }
            //If the Quantity is not greater than one we can skip trade creation
            if (Quantity > 0)
            {
                //Checking to see if the bid user has an entry in the iventory table
                if (threadDataBaseHandler.GetCount("SELECT COUNT(UserID) FROM Inventories WHERE UserID = " + Bid.User + " AND StockName = '" + Bid.StockName + "'") == 0)
                {
                    //If not then an entry for the bid user for this stock is inserted into inventories
                    threadDataBaseHandler.SetData(string.Format("INSERT INTO Inventories(UserID, StockName, Quantity, LastTradedPrice) VALUES({0}, '{1}', {2}, {3})", Bid.User, Bid.StockName, 0, 0));
                }
                //Update the database reflect the new trade
                threadDataBaseHandler.SetData(string.Format("INSERT INTO Trades(StockName, BuyerID, SellerID, Price, Quantity) VALUES('{0}', {1}, {2}, {3}, {4})", Bid.StockName, Bid.User, Offer.User, Offer.Price, Quantity));
                threadDataBaseHandler.SetData(string.Format("UPDATE Inventories set LastTradedPrice = {0}, Quantity = Quantity - {1} WHERE StockName = '{2}' AND UserID = {3}", Offer.Price, Quantity, Offer.StockName, Offer.User));
                threadDataBaseHandler.SetData(string.Format("UPDATE Inventories set LastTradedPrice = {0}, Quantity = Quantity + {1} WHERE StockName = '{2}' AND UserID = {3}", Offer.Price, Quantity, Offer.StockName, Bid.User));
                threadDataBaseHandler.SetData(string.Format("UPDATE Stock SET VolumeTraded = VolumeTraded + {0} WHERE StockName = '{1}'", Quantity, Offer.StockName));
                threadDataBaseHandler.SetData(string.Format("UPDATE Users SET Balance = Balance + {0} WHERE ID = {1}", Offer.Price * Quantity, Offer.User));
                threadDataBaseHandler.SetData(string.Format("UPDATE Users SET Balance = Balance - {0} WHERE ID = {1}", Offer.Price * Quantity, Bid.User));
            }
            else if (Quantity < 0)
            {
                throw new Exception("Error with trade, quantity is less than 0");
            }
            //Checking if trade went ahead
            if (Quantity != 0)
            {
                //If it did then we are updating are local version of the bids and offfers in the server pool
                //This allows the matchmaking algorythim to continue without having to grab the new trade data
                //from the database
                Bid.Quantity   -= Quantity;
                Offer.Quantity -= Quantity;
                //Update database to reflect new trade
                threadDataBaseHandler.SetData(string.Format("Update Pool set Quantity = {0} WHERE Type = {1} AND TimePlaced = '{2}' AND Price = {3} AND User = {4} AND StockName = '{5}'", Bid.Quantity, Bid.Type, Bid.TimePlaced.ToString("yyyy-MM-dd HH:mm:ss"), Bid.Price, Bid.User, Bid.StockName));
                threadDataBaseHandler.SetData(string.Format("Update Pool set Quantity = {0} WHERE Type = {1} AND TimePlaced = '{2}' AND Price = {3} AND User = {4} AND StockName = '{5}'", Offer.Quantity, Offer.Type, Offer.TimePlaced.ToString("yyyy-MM-dd HH:mm:ss"), Offer.Price, Offer.User, Offer.StockName));
            }
            else
            {
                //If they couldn't supply any stock to sell then set the offer quantity to be zero
                Offer.Quantity = 0;
            }
            //Close the connection to the DB so that DB connection thread can be open for the next thread
            threadDataBaseHandler.CloseCon();
        }
Example #6
0
        public async void RunMatchMaker(string s, int ThreadCounter)
        {
            //Store DB connection class from array in Pool in order to not overload the server with conncetions
            threadDataBaseHandler = Pool.DataBaseHandlers[ThreadCounter];
            //Get the Pricelevels of bids for the assigned stock from DB
            MySqlDataReader BidPoolReader  = threadDataBaseHandler.GetData("SELECT DISTINCT Price FROM Pool WHERE Type = 0 AND StockName = '" + s + "' ORDER BY Price ASC");
            List <double>   BidPriceLevels = new List <double>();

            while (BidPoolReader.Read())
            {
                //Read redsults from DB
                BidPriceLevels.Add((double)BidPoolReader["Price"]);
            }
            if (BidPriceLevels.Count == 0)
            {
                return;
            }
            //Get the Pricelevels of offers for the assigned stock from DB
            MySqlDataReader OfferPoolReader  = threadDataBaseHandler.GetData("SELECT DISTINCT Price FROM Pool WHERE Type = 1 AND StockName = '" + s + "' ORDER BY Price DESC");
            List <double>   OfferPriceLevels = new List <double>();

            while (OfferPoolReader.Read())
            {
                //Read redsults from DB
                OfferPriceLevels.Add((double)OfferPoolReader["Price"]);
            }
            if (OfferPriceLevels.Count == 0)
            {
                return;
            }
            //Close connection with DB
            threadDataBaseHandler.CloseCon();
            foreach (double BidPrice in BidPriceLevels)
            {
                for (int i = 0; i < OfferPriceLevels.Count; i++)
                {
                    //Cycle through the bid price levels with every offer price level to find offers which are lower than that of the bid price level
                    if (OfferPriceLevels[i] <= BidPrice)
                    {
                        //if this is the case then lets grab all the bids at this level to be able to assign with offers at this price level
                        MySqlDataReader      BidReader = threadDataBaseHandler.GetData("SELECT * FROM Pool WHERE Type = 0 AND StockName = '" + s + "' AND Price = " + BidPrice);
                        List <BidsAndOffers> bids      = new List <BidsAndOffers>();
                        while (BidReader.Read())
                        {
                            //These are commented out as they are used for debugging
                            //Console.WriteLine(BidReader["Type"].GetType());
                            //Console.WriteLine(BidReader["TimePlaced"].GetType());
                            //Console.WriteLine(BidReader["Price"].GetType());
                            //Console.WriteLine(BidReader["User"].GetType());
                            //Console.WriteLine(BidReader["StockName"].GetType());
                            //Console.WriteLine(BidReader["Quantity"].GetType());
                            //Console.WriteLine(BidReader["TurnsInPool"].GetType());
                            bids.Add(new BidsAndOffers((bool)BidReader["Type"], (DateTime)BidReader["TimePlaced"], (double)BidReader["Price"], (int)BidReader["User"], (string)BidReader["StockName"], (int)BidReader["Quantity"], (int)BidReader["TurnsInPool"]));
                        }
                        //Grab the offers at this price level for assignment
                        MySqlDataReader      OfferReader = threadDataBaseHandler.GetData("SELECT * FROM Pool WHERE Type = 1 AND StockName = '" + s + "' AND Price = " + OfferPriceLevels[i]);
                        List <BidsAndOffers> offers      = new List <BidsAndOffers>();
                        while (OfferReader.Read())
                        {
                            offers.Add(new BidsAndOffers((bool)OfferReader["Type"], (DateTime)OfferReader["TimePlaced"], (double)OfferReader["Price"], (int)OfferReader["User"], (string)OfferReader["StockName"], (int)OfferReader["Quantity"], (int)OfferReader["TurnsInPool"]));
                        }
                        //While there is atleast one offer and one bid available at this price range we allocate them
                        while (bids.Count != 0 && offers.Count != 0)
                        {
                            BidsAndOffers b = bids[0];
                            LMMRound(ref b, ref offers);
                            #region Cleaner
                            foreach (BidsAndOffers o in offers)
                            {
                                if (o.Quantity <= 0)
                                {
                                    TradeManager.RemoveFromPool(o, threadDataBaseHandler);
                                }
                            }
                            offers.RemoveAll((o) => o.Quantity <= 0);
                            bids[0] = b;
                            if (bids[0].Quantity <= 0)
                            {
                                TradeManager.RemoveFromPool(bids[0], threadDataBaseHandler);
                                bids.RemoveAt(0);
                                continue;
                            }
                            #endregion
                            ProRataWithLMM(ref b, ref offers, 5);
                            #region Cleaner
                            foreach (BidsAndOffers o in offers)
                            {
                                if (o.Quantity <= 0)
                                {
                                    TradeManager.RemoveFromPool(o, threadDataBaseHandler);
                                }
                            }
                            offers.RemoveAll((o) => o.Quantity <= 0);
                            bids[0] = b;
                            if (bids[0].Quantity <= 0)
                            {
                                TradeManager.RemoveFromPool(bids[0], threadDataBaseHandler);
                                bids.RemoveAt(0);
                                continue;
                            }
                            #endregion
                            FIFO(ref b, ref offers);
                            #region Cleaner
                            foreach (BidsAndOffers o in offers)
                            {
                                if (o.Quantity <= 0)
                                {
                                    TradeManager.RemoveFromPool(o, threadDataBaseHandler);
                                }
                            }
                            offers.RemoveAll((o) => o.Quantity <= 0);
                            bids[0] = b;
                            if (bids[0].Quantity <= 0)
                            {
                                TradeManager.RemoveFromPool(bids[0], threadDataBaseHandler);
                                bids.RemoveAt(0);
                                continue;
                            }
                            #endregion
                        }
                    }
                }
            }
            threadDataBaseHandler.CloseCon();
        }