//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(); }
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(); }