예제 #1
0
        //Creates from scratch, or 'tops up', or reloads a single day of, an All-Table for a single share for a period
        //spanning tradingSpan trading days starting at startDate.
        //If topupOnly, then a leading number of days get 'skipped' (since the AllTable is assumed to already have the data in it).
        //If reloadOffset is non zero, we skip that number of AllTable records into the AllTable file and then overwrite
        //the succeeding 104 bands (i.e. one days worth)
        //The passed in tradeHash holds the raw trading information needed to create each AllTable record.
        //tradeHash: Key: 'ShareName,YYMMDD,bandNum' e.g. "B+S BANKSYSTEME AG O.N.,180722,1" band 1 is from 09:00:00 to 09:04:59
        //           Value: Trade object with properties shareName,shareNum,tradeDate,line   ... but shareNum at this stage may be 0
        private static void GenerateSingleAllTable(
            CancellationToken ct, string allTableFile, int shareNum, string shareName, DateTime startDate, int tradingSpan,
            ref Dictionary <string, Trade> tradeHash, bool topUpOnly, TopupInformation topupInfo, string reloadDate)
        {
            LogHeaderForGenerateSingleAllTable(allTableFile, startDate, topUpOnly, reloadDate);

            AllTable atRec;
            var      runDate = startDate.AddDays(0);

            //Create or Append to AllTable file?
            FileMode mode;

            if (reloadDate.Length == 6)
            {
                // we are reloading... reloadDate = YYMMDD
                mode = FileMode.Open;
            }
            else
            {
                //more usual case
                mode = topUpOnly ? FileMode.Append : FileMode.Create;
            }

            using (FileStream fs = new FileStream(allTableFile, mode))
            {
                int rowNum = 0;
                if (reloadDate.Length == 6)
                {
                    //RELOAD of a single day
                    // advance the seek position to the start of the day we want to overwrite
                    var bf = new BinaryFormatter();
                    while (fs.Position != fs.Length)
                    {
                        var lastPos = fs.Position;
                        var testAt  = (AllTable)bf.Deserialize(fs);
                        rowNum++;
                        if (testAt.Date == reloadDate)
                        {
                            fs.Position = lastPos; // back up
                            rowNum--;
                            break;                 // and go on to writing out 104 bands
                        }
                    }
                    if (fs.Position == fs.Length)
                    {
                        Helper.LogStatus("Error", $"Could not find reloadDate '{reloadDate}' records in All-Table {allTableFile}");
                        fs.Dispose();
                        return;
                    }
                }
                else
                {
                    if (topUpOnly)
                    {
                        //we're appending...
                        //no need to write rows 1 and 2 if this is a topup
                        //get starting RowNum to use from passed in TopupInformation
                        rowNum = topupInfo.LastRow[shareNum] + 1;
                    }
                    else
                    {
                        //we're creating from scratch
                        //do the first 2 rows right away (they are special)
                        atRec = AllTableFactory.InitialRow(rowNum++, "YYMMDD", "Day", "TimeFrom", "TimeTo");
                        Helper.SerializeAllTableRecord(fs, atRec);
                        atRec = AllTableFactory.InitialRow(rowNum++, "", "", "", "");
                        Helper.SerializeAllTableRecord(fs, atRec);
                    }
                }

                //now consider every day in the trading span, but if topUpOnly, skip over those we already have.
                int tradingDays = 0; double yesterPrice = 0; double lastPrice = 0;
                while (!ct.IsCancellationRequested && tradingDays < tradingSpan)
                {
                    if (Helper.IsTradingDay(runDate))
                    {
                        //var rowDate = runDate.ToShortDateString().Replace("/", "").Substring(2); //YYMMDD in en-ZA culture
                        var rowDate      = runDate.ToString("yyMMdd"); // culture independent
                        var topupInfoKey = $"{rowDate},{shareNum}";
                        if (!topUpOnly || !topupInfo.DatesData[topupInfoKey].AlreadyHave)
                        {
                            //each day has 104 five-minute bands from 09h00 to 17h40 - save each one as an 'at' record to disk
                            var rowDay = runDate.DayOfWeek.ToString().Substring(0, 3);
                            lastPrice = yesterPrice;
                            for (int timeBand = 0; timeBand < 104; timeBand++)
                            {
                                int minsIntoDay = 9 * 60 + 5 * timeBand;
                                int hr          = minsIntoDay / 60;
                                int min         = minsIntoDay % (60 * hr);

                                string timeFrom = hr.ToString("00") + ":" + min.ToString("00") + ":00";
                                string timeTo   = hr.ToString("00") + ":" + (min + 4).ToString("00") + ":59";

                                atRec    = AllTableFactory.InitialRow(rowNum++, rowDate, rowDay, timeFrom, timeTo);
                                atRec.FP = lastPrice;
                                // now fill from passed in tradeHash
                                lastPrice = FillAllTableRowFromTradehash(shareNum, atRec, timeBand + 1, tradeHash, lastPrice);
                                //save AllTable row record to disk - this will be overwriting of reloadDate has been set
                                Helper.SerializeAllTableRecord(fs, atRec);
                            }
                            yesterPrice = lastPrice;
                        }
                        tradingDays++;
                    }
                    runDate = runDate.AddDays(1);
                }
            }
            if (ct.IsCancellationRequested)
            {
                //delete the All-Table file just saved
                try
                {
                    File.Delete(allTableFile);
                }
                catch (Exception ex)
                {
                }
            }
        }
예제 #2
0
        // Sweep thru the the shares either deleting early part of existing All-Tables or
        // the entire file (depending on passed in topUp parameter)
        // If topUpOnly is true, data in the All-Tables is effectively 'shuffled up'.
        // If topUpOnly is false, each All-Table is deleted.
        // This will leave an All-Table to which data must be appended (or else which must be written anew,
        // which is akin to appending to a zero size file)
        // Also, once complete, there will in general be a tail bit of the toupInfo object for whose dates have
        // values of 'alreadyHave' remaining false.
        // These will be the dates for which new All-Table records will need to be appended
        private static void PrepareAllTables(ref TopupInformation topupInfo, DateTime startDate,
                                             int tradingSpan, string[] allShares, bool topUpOnly, Action <string> progress)
        {
            var atPath = Helper.UserSettings().AllTablesFolder;

            var msg = $"Preparing all *.at files";

            progress(msg);
            Helper.Log("Info", msg);
            //var shares = allShares;
            foreach (string share in allShares)
            {
                Match m = Regex.Match(share, @"(.+)\s(\d+)$");
                if (m.Success)
                {
                    var shareName    = m.Groups[1].Value.TrimEnd();
                    var shareNum     = Convert.ToInt32(m.Groups[2].Value);
                    var allTableFile = atPath + @"\" + $"alltable_{shareNum}.at";
                    var tmpFile      = allTableFile + ".tmp";
                    if (File.Exists(allTableFile))
                    {
                        if (topUpOnly)
                        {
                            //prepare a 'new' all-table file by skipping over data in the existing all-table which has fallen
                            //out of range, retaining the run of records to the end (for subsequent appending to with new data)
                            //essentially chopping off the first bit.
                            using (FileStream fs1 = new FileStream(allTableFile, FileMode.Open))
                            {
                                //read entire existing alltable file into memory (can be 10400 records!)
                                var oldRows = Helper.DeserializeAllTable <AllTable>(fs1).Skip(2).ToList();

                                //skip to first record in oldRows holding the first wanted date, then start writing to a NEW version
                                using (FileStream fs2 = new FileStream(tmpFile, FileMode.Create, FileAccess.Write, FileShare.None, 131072)) // 128K
                                {
                                    //do the first 2 rows right away (they are special)
                                    Helper.SerializeAllTableRecord(fs2, AllTableFactory.InitialRow(0, "YYMMDD", "Day", "TimeFrom", "TimeTo"));
                                    Helper.SerializeAllTableRecord(fs2, AllTableFactory.InitialRow(1, "", "", "", ""));

                                    int rowNum = 2;
                                    foreach (AllTable at in oldRows)
                                    {
                                        // must this old row be kept?
                                        var topupInfoKey = $"{at.Date},{shareNum}";
                                        // key may not be found if previously the date was processed and subsequently was
                                        // classified a public holiday. (it would have had no trading, all bands empty anyway)
                                        if (topupInfo.DatesData.ContainsKey(topupInfoKey) && topupInfo.DatesData[topupInfoKey].Wanted)
                                        {
                                            //yes, so append it to tmp file
                                            at.Row = rowNum;
                                            at.F   = rowNum - 1;
                                            Helper.SerializeAllTableRecord(fs2, at);
                                            //note that we now have data for the date (will be repeatedly done for 104 such bands)
                                            topupInfo.DatesData[topupInfoKey].AlreadyHave = true;
                                            topupInfo.LastRow[shareNum] = at.Row;
                                            rowNum++;
                                        }
                                    }
                                }
                            }
                            //delete old alltable and replace with smaller new one, to which new data will be appended
                            if (File.Exists(tmpFile))
                            {
                                File.Delete(allTableFile);
                                File.Move(tmpFile, allTableFile);
                                progress($"AllTable prepared, (share {shareNum})");
                            }
                        }
                        else
                        {
                            File.Delete(allTableFile);
                            progress($"{allTableFile} deleted...");
                        }
                    }
                    var auditFile = atPath + @"\Audit\" + $"{shareNum.ToString("000")}.txt";
                    if (File.Exists(auditFile))
                    {
                        if (topUpOnly)
                        {
                            //TODO: decide if Audit file should be peserved and allowed to grow indefinitely
                            File.Delete(auditFile);
                        }
                        else
                        {
                            File.Delete(auditFile);
                        }
                    }
                }
            }
            Helper.Log("Info", $"{allShares.Count()} '.at' files participating");
        }