2010-11-21 16 views
1

Ich arbeite mit einem Stock-Daten-Feed und möchte aus den Daten winzige Balken (Candlesticks) erstellen. Ich denke, dass ich eine ziemlich gute Frage habe, die mir die Daten geben wird, die ich brauche, aber ich bin nicht sicher, dass es der beste Weg ist, darüber zu gehen. Bitte geben Sie Kommentare oder Kritik, die Sie haben, ich bin offen für jede Eingabe, die Sie geben möchten.Sind Aggregaterweiterungen der beste Weg, um dieses Problem zu lösen, oder sollte ich versuchen, etwas mit der Gruppierung zu tun?

Eingang auf der linken Seite und Ausgang auf der rechten Seite

class StockTick 
{ 
    public DateTime Timestamp { get; set; } 

    public int Id { get; set; } 

    public decimal LastPrice { get; set; } 
} 

class FirstUda : CepAggregate<decimal, decimal> 
{ 
    public override decimal GenerateOutput(IEnumerable<decimal> payloads) 
    { 
     return payloads.First(); 
    } 
} 

class LastUda : CepAggregate<decimal, decimal> 
{ 
    public override decimal GenerateOutput(IEnumerable<decimal> payloads) 
    { 
     return payloads.Last(); 
    } 
} 

public static class CepExtensions 
{ 
    [CepUserDefinedAggregate(typeof(FirstUda))] 
    public static decimal First<InputT>(this CepWindow<InputT> window, Expression<Func<InputT, decimal>> map) 
    { 
     throw CepUtility.DoNotCall(); 
    } 

    [CepUserDefinedAggregate(typeof(LastUda))] 
    public static decimal Last<InputT>(this CepWindow<InputT> window, Expression<Func<InputT, decimal>> map) 
    { 
     throw CepUtility.DoNotCall(); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (var server = Server.Create("Default")) 
     { 
      var app = server.CreateApplication("app"); 

      var source = GetStockTick(); 

      var input = source.ToPointStream(
       app, 
       t => PointEvent.CreateInsert(t.Timestamp, t), 
       AdvanceTimeSettings.IncreasingStartTime); 

      var minuteWindows = input.AlterEventDuration(e => TimeSpan.FromTicks(TimeSpan.TicksPerMinute - (e.StartTime.Ticks % TimeSpan.TicksPerMinute))); 

      var highLowTicks = from e in minuteWindows 
           group e by e.Id into g 
           from win in g.SnapshotWindow(SnapshotWindowOutputPolicy.Clip) 
           select new 
           { 
            Id = g.Key, 
            Timestamp = win.Max(e => e.Timestamp.AddSeconds(e.Timestamp.Second * -1)), 
            OpenPrice = win.First(e => e.LastPrice), 
            HighPrice = win.Max(t => t.LastPrice), 
            LowPrice = win.Min(t => t.LastPrice), 
            ClosePrice = win.Last(e => e.LastPrice) 
           }; 

      foreach (var hl in highLowTicks.ToEnumerable()) 
      { 
       Console.WriteLine(hl); 
      } 

      Console.ReadKey(); 
     } 
    } 

    private static IEnumerable<StockTick> GetStockTick() 
    { 
     var ticks = new List<StockTick>(); 

     var baseTime = new DateTime(2010, 1, 1, 12, 0, 0); 

     ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(1), LastPrice = 10 }); 
     ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(15), LastPrice = 8 }); 
     ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(30), LastPrice = 12 }); 
     ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(45), LastPrice = 11 }); 
     ticks.Add(new StockTick() { Id = 1, Timestamp = baseTime.AddSeconds(65), LastPrice = 13 }); 

     ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(11), LastPrice = 35 }); 
     ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(13), LastPrice = 37 }); 
     ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(50), LastPrice = 22 }); 
     ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(55), LastPrice = 32 }); 
     ticks.Add(new StockTick() { Id = 2, Timestamp = baseTime.AddSeconds(61), LastPrice = 36 }); 

     return ticks.OrderBy(t => t.Timestamp); 
    } 
} 

Antwort

0

Ryan, Sieht gut aus - nur zu prüfen, ob dies die beabsichtigte Semantik:

Sie werden in jeder Minute mehrere Ergebnisse erhalten. Für jedes Eingabe-Ereignis erhalten Sie ein Ergebnis-Ereignis mit der gleichen Startzeit, das die erste (in dieser Minute) und den aktuellen Preis sowie die in dieser Minute bisher aufgetretenen Min- und Max-Werte enthält. Daher enthält nur das allerletzte Ergebnis-Ereignis innerhalb jeder Minute das erste, letzte, minimale und maximale der gesamten Minute. Richtig? Sie wollen nicht nur eine Veranstaltung pro Minute?

Roman

+0

Ich möchte nicht ein Ereignis für jede ganze Minute. Ich möchte eine aktualisierte "Minutenleiste" jedes Mal, wenn ein Ereignis kommt. Sie haben Recht, das allerletzte Ereignis in der Minute wird den Endstatus der Minutenleiste definieren, aber jedes Ereignis innerhalb der Minute wird eine aktualisierte Minutenleiste zur Verfügung stellen verwendet werden, um Abfragen in der Mitte der Minute zu erfüllen. –

+0

Ich versuche 1min Balken mit Hopping Window der Länge 1min Länge alle 1min zu erstellen. Was ich nicht verstehe, ist, wie man die aktuelle Zeitrahmenzeit erhält, weil es keine First() - Methode für HoppingWindow gibt. – Chris