Пример #1
0
 public bool SellPolicy(StockEntity currentStockEntity, StockEntity lastBoughtStockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedAllStockEntities)
 {
     if (currentStockEntity.Close == 0)
     {
         return false;
     }
     bool biasSellDecesion = false;
     if (currentStockEntity.GetMA(20) != 0)
     {
         double bias = (currentStockEntity.GetMA(5) - currentStockEntity.GetMA(20)) / currentStockEntity.GetMA(5);
         if (bias > tooStrongTheashold)
         {
             biasSellDecesion = true;
             int index = sortedAllStockEntities.FindIndex(entity => entity.RowKey == currentStockEntity.RowKey);
             if (index > 1)
             {
                 var lastStockEntity = sortedAllStockEntities[index - 1];
                 if ((currentStockEntity.Close - lastStockEntity.Close) / lastStockEntity.Close > 0.05)
                 {
                     Console.WriteLine("Stock is too strong, ignore sell decesion.");
                     biasSellDecesion = false;
                 }
             }
         }
         else if (bias < balenceThreshold && bias >= tooWeakThreshold)
         {
             biasSellDecesion = true;
         }
     }
     return biasSellDecesion;
 }
 public bool SellPolicy(StockEntity currentStockEntity, StockEntity lastBoughtStockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedAllStockEntities)
 {
     bool sc1 = MARules.MA5AboveMA20(currentStockEntity, 0.1) && (MARules.PriceBelowMA5(currentStockEntity, 0.1) || MARules.PriceBelowMA20(currentStockEntity, 0));
     bool sc2 = !MARules.MA5AboveMA20(currentStockEntity, 0.1) && MARules.PriceBelowMA5(currentStockEntity, 0.02);
     bool sc3 = VolumeRules.PriveAboveButVolumeBelowLastBought(currentStockEntity, lastBoughtStockEntity, 0.1);
     return (sc1 || sc2 || sc3);
 }
Пример #3
0
 public bool BuyPolicy(StockEntity currentStockEntity, StockEntity lastBoughtStockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedAllStockEntities)
 {
     if (currentStockEntity.Close == 0)
     {
         return false;
     }
     bool biasBuyDecesion = false;
     if (currentStockEntity.GetMA(20) == 0)
     {
         biasBuyDecesion = true;
     }
     else
     {
         double bias = (currentStockEntity.GetMA(5) - currentStockEntity.GetMA(20)) / currentStockEntity.GetMA(5);
         if (bias <= tooStrongTheashold && bias >= balenceThreshold)
         {
             biasBuyDecesion = true;
         }
         else if (bias < tooWeakThreshold)
         {
             biasBuyDecesion = true;
         }
     }
     return biasBuyDecesion;
 }
 public bool BuyPolicy(StockEntity currentStockEntity, StockEntity lastBoughtStockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedAllStockEntities)
 {
     bool bc1 = MARules.PriceAboveMA5(currentStockEntity, 0);
     bool bc2 = MARules.MA5Rising(currentStockEntity, sortedAllStockEntities, 5);
     bool bc3 = MARules.PriceAboveMA20(currentStockEntity, 0);
     bool bc4 = PriceRules.PriceDiffAboveDelta(currentStockEntity, lastSoldStockEntity, 0.1);
     bool bc5 = VolumeRules.VolumeAboveLast5(currentStockEntity, lastSoldStockEntity, sortedAllStockEntities, 0.1);
     bool bc6 = MARules.MA20Rising(currentStockEntity, sortedAllStockEntities, 3);
     return (bc1 && bc2 && bc3 && bc4 && bc5 && bc6);
 }
Пример #5
0
 public bool SellPolicy(StockEntity currentStockEntity, StockEntity lastBoughtStockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedAllStockEntities)
 {
     bool sc1 = !(MARules.MA20Rising(currentStockEntity, sortedAllStockEntities, 5) && MARules.PriceAboveMA20(currentStockEntity, 0.05));
     bool sc2 = !(!MARules.MA20Rising(currentStockEntity, sortedAllStockEntities, 5) && MARules.PriceAboveMA20(currentStockEntity, 0));
     bool rtn = (sc1 || sc2);
     if (rtn)
     {
         Console.WriteLine("{0}: Sell condition met: {1},{2}", currentStockEntity.Date.ToString("yyyy-MM-dd"), sc1, sc2);
     }
     return rtn;
 }
Пример #6
0
        public static bool PriceDiffAboveDelta(StockEntity stockEntity, StockEntity lastSoldStockEntity, double delta)
        {
            if (lastSoldStockEntity == null) return true;

            if (Math.Abs(stockEntity.Close - lastSoldStockEntity.Close) / stockEntity.Close >= delta)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
 public bool SellPolicy(StockEntity currentStockEntity, StockEntity lastBoughtStockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedAllStockEntities)
 {
     bool sc1 = MARules.MA5AboveMA20(currentStockEntity, 0.1) && (MARules.PriceBelowMA5(currentStockEntity, 0.1) || MARules.PriceBelowMA20(currentStockEntity, 0));
     double belowMA5Delta = 0.05;
     if (VolumeRules.VolumeBelowLastBought(currentStockEntity, lastBoughtStockEntity, 0.6)) belowMA5Delta = 0.02;
     bool sc2 = !MARules.MA5AboveMA20(currentStockEntity, 0.1) && MARules.MA5AboveMA20(currentStockEntity, 0) && (MARules.PriceBelowMA5(currentStockEntity, belowMA5Delta) || MARules.PriceBelowMA20(currentStockEntity, 0));
     bool sc3 = MARules.PriceBelowMA20(currentStockEntity, 0);
     bool sc4 = !MARules.MA5AboveMA20(currentStockEntity, 0.1) && PriceRules.PriceBelowLast5IfCloseToMA5(currentStockEntity, sortedAllStockEntities, -0.02, 0.02) && PriceRules.PriceAboveLastBought(currentStockEntity, lastBoughtStockEntity, 0);
     bool sc5 = MARules.PriceBelowMA5(currentStockEntity, 0) && PriceRules.PriceBelowLastBought(currentStockEntity, lastBoughtStockEntity, 0.1);
     
     bool rtn = (sc1 || sc2 || sc3 || sc4 || sc5);
     if (rtn)
     {
         Console.WriteLine("{0}: Sell condition met: {1},{2},{3},{4},{5}", currentStockEntity.Date.ToString("yyyy-MM-dd"), sc1, sc2, sc3, sc4, sc5);
     }
     return rtn;
 }
Пример #8
0
 public static bool MA20Rising(StockEntity stockEntity, List<StockEntity> sortedStockEntities, int continousCount, double increasingRate = 0)
 {
     int index = sortedStockEntities.IndexOf(stockEntity);
     double lastMA20 = -1;
     for (int i = Math.Max(0, index - continousCount + 1); i < index + 1; i++)
     {
         if (lastMA20 < 0)
         {
             lastMA20 = sortedStockEntities[i].GetMA(20);
         }
         else
         {
             if (sortedStockEntities[i].GetMA(20) < lastMA20 * (1 + increasingRate)) return false;
             else lastMA20 = sortedStockEntities[i].GetMA(20);
         }
     }
     return true;
 }
Пример #9
0
        public static void CalculateRealTimeMA(string storageConnectionString, StockEntity stockEntity)
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
            tableClient.DefaultRequestOptions.RetryPolicy = new ExponentialRetry(TimeSpan.FromSeconds(30), 10);
            CloudTable table = tableClient.GetTableReference(Constants.StorageStockTableName);

            TableOperation retrieveStockEntityStatus = TableOperation.Retrieve<StockEntityStatus>("status-" + stockEntity.PartitionKey, "status");
            var stockEntityStatus = (StockEntityStatus)table.Execute(retrieveStockEntityStatus).Result;
            if (stockEntityStatus == null || stockEntityStatus.LastestRawDataDate == DateTime.FromFileTimeUtc(0) || stockEntityStatus.GetLatestMAStartDate(stockEntityStatus.GetMaxAvailableMADataIndex()) == DateTime.FromFileTimeUtc(0))
            {
                throw new InvalidOperationException("Please upload data and do initial processing first.");
            }
            TableOperation tableQuery = TableOperation.Retrieve<StockEntity>(stockEntity.PartitionKey, stockEntityStatus.LastestRawDataDate.ToString("yyyy-MM-dd"));
            var lastestClosedStockEntity = (StockEntity)table.Execute(tableQuery).Result;

            string pkFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, stockEntity.PartitionKey);
            string rkLowerFilter = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, stockEntityStatus.GetLatestMAStartDate(stockEntityStatus.GetMaxAvailableMADataIndex()).Subtract(TimeSpan.FromDays(10)).ToString("yyyy-MM-dd"));
            string rkHigherFilter = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, stockEntity.RowKey);
            string combinedFilter = TableQuery.CombineFilters(pkFilter, TableOperators.And, rkLowerFilter);
            combinedFilter = TableQuery.CombineFilters(combinedFilter, TableOperators.And, rkHigherFilter);
            TableQuery<StockEntity> query = new TableQuery<StockEntity>().Where(combinedFilter);
            var sortedStockEntities = table.ExecuteQuery<StockEntity>(query).OrderByDescending(entity => entity.Date).Take(stockEntityStatus.GetMaxAvailableMADataIndex() - 1).ToList();

            double sum = stockEntity.Close;
            int[] MADataAvailable = stockEntityStatus.GetAvailableMADataIndex();
            int MADataIndex = 0;
            for (int i = 0; i < sortedStockEntities.Count; i++)
            {
                sum += sortedStockEntities[i].Close;
                if (i == MADataAvailable[MADataIndex] - 2)
                {
                    stockEntity.SetMA(MADataAvailable[MADataIndex], sum / MADataAvailable[MADataIndex]);
                    MADataIndex++;
                }
            }
            if (sortedStockEntities.Count == (stockEntityStatus.GetMaxAvailableMADataIndex() - 1))
            {
                stockEntity.SetMA(stockEntityStatus.GetMaxAvailableMADataIndex(), sum / stockEntityStatus.GetMaxAvailableMADataIndex());
            }
        }
Пример #10
0
 public static bool PriceBelowLast5IfCloseToMA5(StockEntity stockEntity, List<StockEntity> sortedStockEntities, double deltaForPrice, double deltaForMA5)
 {
     if (stockEntity.Close < stockEntity.GetMA(5) * (1 + deltaForMA5))
     {
         int index = sortedStockEntities.IndexOf(stockEntity);
         double lastMinPrice = double.MaxValue;
         for (int i = Math.Max(0, index - 5); i < index; i++)
         {
             if (sortedStockEntities[i].Close <= lastMinPrice) lastMinPrice = sortedStockEntities[i].Close;
         }
         if (stockEntity.Close < lastMinPrice * (1 - deltaForPrice))
         {
             return true;
         }
     }
     else
     {
         return false;
     }
     return false;
 }
Пример #11
0
        public static bool PriceAboveLast5IfInShortPeriod(StockEntity stockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedStockEntities, double delta)
        {
            if (lastSoldStockEntity == null) return true;

            if (stockEntity.Date.Subtract(lastSoldStockEntity.Date) <= TimeSpan.FromDays(7))
            {
                int index = sortedStockEntities.IndexOf(stockEntity);
                double lastMaxPrice = 0;
                for (int i = Math.Max(0, index - 5); i < index; i++)
                {
                    if (sortedStockEntities[i].Close >= lastMaxPrice) lastMaxPrice = sortedStockEntities[i].Close;
                }
                if (stockEntity.Close > lastMaxPrice * (1 + delta))
                {
                    return true;
                }
            }
            else
            {
                return true;
            }
            return false;
        }
Пример #12
0
        public static bool PriceBelowLastBought(StockEntity stockEntity, StockEntity lastBoughtStockEntity, double delta)
        {
            if (lastBoughtStockEntity == null) return false;

            return stockEntity.Close < lastBoughtStockEntity.Close * (1 - delta);
        }
Пример #13
0
        public static bool PriceAboveLastBought(StockEntity stockEntity, StockEntity lastBoughtStockEntity, double delta)
        {
            if (lastBoughtStockEntity == null) return true;

            return stockEntity.Close > lastBoughtStockEntity.Close * (1 + delta);
        }
 private StockEntity GetTecentStockData(string stockCode)
 {
     if (azureToTecentApiMapping.ContainsKey(stockCode))
     {
         string tecentApiStockCode = azureToTecentApiMapping[stockCode];
         StockEntity stockEntity = new StockEntity(stockCode, DateTimeOffset.Parse(DateTime.Today.ToString("yyyy-MM-dd")).DateTime);
         string onlineData = string.Format(downloadTecentRealtimeStockDataApiStr, tecentApiStockCode);
         int retry = 0;
         while (retry < 10)
         {
             try
             {
                 using (var client = new WebClient())
                 {
                     Console.WriteLine("Getting data from {0}", onlineData);
                     byte[] data = client.DownloadData(onlineData);
                     string[] dataStr = Encoding.Default.GetString(data).Split(tecentRealtimeStockDataSplitter);
                     stockEntity.Close = double.Parse(dataStr[indexOfPriceInTecentRealtimeStockData]);
                     stockEntity.AdjClose = double.Parse(dataStr[indexOfPriceInTecentRealtimeStockData]);
                     stockEntity.High = double.Parse(dataStr[indexOfHighPriceInTecentRealtimeStockData]);
                     stockEntity.Low = double.Parse(dataStr[indexOfLowPriceInTecentRealtimeStockData]);
                     stockEntity.Open = double.Parse(dataStr[indexOfOpenPriceInTecentRealtimeStockData]);
                     stockEntity.Volume = double.Parse(dataStr[indexOfVolumeInTecentRealtimeStockData]) * 100;
                 }
                 break;
             }
             catch (Exception ex)
             {
                 Console.WriteLine("Got exception when getting data: {0}", ex.ToString());
                 retry++;
                 Thread.Sleep(TimeSpan.FromSeconds(retry));
             }
         }
         return stockEntity;
     }
     else
     {
         throw new InvalidOperationException(string.Format("Cannot find tecent api code for stock: {0}", stockCode));
     }
 }
Пример #15
0
 public static bool PriceBelowMA20(StockEntity stockEntity, double delta)
 {
     return stockEntity.Close < stockEntity.GetMA(20) * (1 - delta);
 }
 private StockEntity SellStock(StockEntity stockEntity, ref double money, ref double quantity)
 {
     Console.WriteLine("{0}: Sell at price {1}, MA5: {2}, MA20: {3}, Vol: {4}", stockEntity.Date.ToString("yyyy-MM-dd"), stockEntity.Close, stockEntity.GetMA(5), stockEntity.GetMA(20), stockEntity.Volume);
     money = quantity * stockEntity.Close;
     quantity = -1;
     return stockEntity;
 }
Пример #17
0
 public static bool MA5AboveMA20(StockEntity stockEntity, double delta)
 {
     return stockEntity.GetMA(5) > stockEntity.GetMA(20) * (1 + delta);
 }
Пример #18
0
 public bool BuyPolicy(StockEntity currentStockEntity, StockEntity lastBoughtStockEntity, StockEntity lastSoldStockEntity, List<StockEntity> sortedAllStockEntities)
 {
     bool bc1 = MARules.PriceAboveMA20(currentStockEntity, 0);
     bool bc2 = MARules.MA20Rising(currentStockEntity, sortedAllStockEntities, 5, 0.01);
     return (bc1 && bc2);
 }
Пример #19
0
        public static bool VolumeBelowLastBought(StockEntity stockEntity, StockEntity lastBoughtStockEntity, double delta)
        {
            if (lastBoughtStockEntity == null) return true;

            return stockEntity.Volume < lastBoughtStockEntity.Volume * (1 - delta);
        }
Пример #20
0
        public static bool PriveAboveButVolumeBelowLastBought(StockEntity stockEntity, StockEntity lastBoughtStockEntity, double delta)
        {
            if (lastBoughtStockEntity == null) return true;

            return stockEntity.Close >= lastBoughtStockEntity.Close && stockEntity.Volume < lastBoughtStockEntity.Volume * (1 - delta);
        }
Пример #21
0
 public static bool PriceAboveMA20(StockEntity stockEntity, double delta)
 {
     return stockEntity.Close > stockEntity.GetMA(20) * (1 + delta);
 }
 private List<StockEntity> ReadStockDataFromFileSource(string fileDataSource, string azureTableStockCode)
 {
     List<StockEntity> stockEntities = new List<StockEntity>();
     Console.WriteLine("Parsing data from {0}", fileDataSource);
     using (StreamReader reader = new StreamReader(fileDataSource))
     {
         string line = reader.ReadLine();
         if (line != "Date,Open,High,Low,Close,Volume,Adj Close")
         {
             throw new InvalidOperationException("File data source format has been changed!");
         }
         while (!reader.EndOfStream)
         {
             line = reader.ReadLine();
             string[] splitters = line.Split(new char[] { ',' });
             if (splitters.Length == 7)
             {
                 try
                 {
                     DateTime date = DateTime.Parse(splitters[0]);
                     double open = double.Parse(splitters[1]);
                     double high = double.Parse(splitters[2]);
                     double low = double.Parse(splitters[3]);
                     double close = double.Parse(splitters[4]);
                     double volume = double.Parse(splitters[5]);
                     double adjClose = double.Parse(splitters[6]);
                     var stockEntity = new StockEntity(azureTableStockCode, date)
                     {
                         Open = open,
                         High = high,
                         Low = low,
                         Close = close,
                         Volume = volume,
                         AdjClose = adjClose
                     };
                     stockEntities.Add(stockEntity);
                 }
                 catch
                 {
                 }
             }
         }
     }
     return stockEntities;
 }
        public double CheckWinRate(string azureTableStockCode, ITradePolicy policy, string dateTimeSince = "1990-01-01", bool noDividend = false, bool saveResult = false)
        {
            CloudTable table = GetAzureTable();

            string pkFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, azureTableStockCode);
            string rkFilter = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, dateTimeSince);
            string combinedFilter = TableQuery.CombineFilters(pkFilter, TableOperators.And, rkFilter);
            TableQuery<StockEntity> query = new TableQuery<StockEntity>().Where(combinedFilter);
            var sortedStockEntities = table.ExecuteQuery<StockEntity>(query).OrderBy(entity => entity.Date).ToList();

            double money = 1000;
            double quantity = -1;
            StockEntity lastBoughtStockEntity = new StockEntity();
            StockEntity lastSoldStockEntity = new StockEntity();
            StockEntity yesterdayStockEntity = null;
            long winCount = 0;
            long hugeWinCount = 0;
            long loseCount = 0;
            long hugeLoseCount = 0;

            foreach (var stockEntity in sortedStockEntities)
            {
                if (quantity < 0)
                {
                    if (policy.BuyPolicy(stockEntity, lastBoughtStockEntity, lastSoldStockEntity, sortedStockEntities))
                    {
                        lastBoughtStockEntity = BuyStock(stockEntity, ref money, ref quantity);
                    }
                }
                else if (quantity > 0)
                {
                    bool bonusDividend = false;
                    double devidendRate = 1;
                    if (!noDividend)
                    {
                        if (yesterdayStockEntity != null && stockEntity.Open > 0 && stockEntity.Open < yesterdayStockEntity.Close * 0.9)
                        {
                            Console.WriteLine("It's impossible that much lose happened, bonus dividend must have happened!");
                            bonusDividend = true;
                            devidendRate = yesterdayStockEntity.Close / stockEntity.Open;
                            quantity *= devidendRate;
                        }
                    }
                    if (policy.SellPolicy(stockEntity, lastBoughtStockEntity, lastSoldStockEntity, sortedStockEntities))
                    {
                        lastSoldStockEntity = SellStock(stockEntity, ref money, ref quantity);
                        if (stockEntity.Close * devidendRate > lastBoughtStockEntity.Close)
                        {
                            Console.WriteLine("{0}: Win {1}%", stockEntity.Date.ToString("yyyy-MM-dd"), (stockEntity.Close * devidendRate - lastBoughtStockEntity.Close) / lastBoughtStockEntity.Close * 100);
                            winCount++;
                            if (stockEntity.Close * devidendRate > lastBoughtStockEntity.Close * 1.1)
                            {
                                hugeWinCount++;
                            }
                        }
                        else
                        {
                            Console.WriteLine("{0}: Lose {1}%", stockEntity.Date.ToString("yyyy-MM-dd"), (lastBoughtStockEntity.Close - stockEntity.Close * devidendRate) / lastBoughtStockEntity.Close * 100);
                            loseCount++;
                            if (!bonusDividend && stockEntity.Close < lastBoughtStockEntity.Close * 0.9)
                            {
                                hugeLoseCount++;
                            }
                        }
                    }
                }
                yesterdayStockEntity = stockEntity;
            }
            if (quantity > 0 && sortedStockEntities.LongCount() > 0)
            {
                money = sortedStockEntities.Last().Close * quantity;
            }
            Console.WriteLine("{4}: Money at the end is {0}, win count = {1}, huge win count = {5}, lose count = {2}, huge lose count = {6}, win rate = {3}%", money, winCount, loseCount, (double)winCount * 100 / (winCount + loseCount), azureTableStockCode, hugeWinCount, hugeLoseCount);
            if (saveResult)
            {
                TableOperation retrieveStockEntityStatus = TableOperation.Retrieve<StockEntityStatus>("status-" + azureTableStockCode, "status");
                var stockEntityStatus = (StockEntityStatus)table.Execute(retrieveStockEntityStatus).Result;
                if (stockEntityStatus == null)
                {
                    throw new InvalidOperationException("Please upload data and do initial processing first.");
                }
                if (dateTimeSince == "1990-01-01")
                {
                    stockEntityStatus.OverallWinRate = (double)winCount * 100 / (winCount + loseCount);
                    stockEntityStatus.OverallProfitRate = (money - 1000) * 100 / 1000;
                }
                else
                {
                    stockEntityStatus.RecentWinRate = (double)winCount * 100 / (winCount + loseCount);
                    stockEntityStatus.RecentProfitRate = (money - 1000) * 100 / 1000;
                }
                table.Execute(TableOperation.InsertOrMerge(stockEntityStatus));
            }
            return (double)winCount * 100 / (winCount + loseCount);
        }