微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何根据连续的即将来临的数据c#形成5分钟的高低开盘价?

如何解决如何根据连续的即将来临的数据c#形成5分钟的高低开盘价?

我有一个websocket api,它每秒不断向我提供数据。我的目标是根据此数据形成5分钟的开盘高低。

这是Python代码,它们在Python中也是如此:https://gist.github.com/oldmonkABA/f73f5d67bcf85316ac0470919bf54e17

我尝试使用下面的OnTick方法,每1秒调用一次,每秒钟发送一次数据,如下所示:

{"InstrumentToken":260105,"LastPrice":23616.6,"Timestamp":"2020-10-16T16:35:01"}

所以每秒钟我都会得到具有不同LastPrice和Timestamp的相同json,如

{"InstrumentToken":260105,"LastPrice":23620,"Timestamp":"2020-10-16T14:38:02"}

{"InstrumentToken":260105,"LastPrice":23622,"Timestamp":"2020-10-16T14:38:03"}

以此类推,直到:

{"InstrumentToken":260105,"LastPrice":23644,"Timestamp":"2020-10-16T14:39:59"}

现在在对象latestTickData下,我正在收集所有这些数据,预期的输出是:

打开= 23616.6,因为这是基于“时间戳记”的初始价格:“ 2020-10-16T14:35:01”。

关闭= 23644,基于其最近5分钟的价格“时间戳”:“ 2020-10-16T14:39:59”。

高=我可以使用MAX(所有5分钟数据)。

低=我可以使用MIN(所有5分钟数据)

C#代码

private static void OnTick(Tick TickData)
{
    Console.WriteLine("Tick " + Utils.JsonSerialize(TickData));

    var latestTickData = new MyObject()
    {
        InstrumentID = TickData.InstrumentToken,Close = TickData.LastPrice,High = TickData.LastPrice,Low = TickData.LastPrice,Open = TickData.LastPrice,TimeStamp = TickData.Timestamp.HasValue ? TickData.Timestamp.Value : DateTime.Now
    };

现在我将每秒收集一次新数据到latestTickData中。

我要根据此数据形成5分钟开盘高低。

我当时想像在时间戳和最小最大函数上进行分组,以查找高低,但是代码不起作用。

我尝试使用此代码,但此代码不在ontick方法上计算正在进行的数据:

var resultSet = MydataList.GroupBy(i => i.GetStartOfPeriodByMins(5))
           .Select(gr =>
          new
          {
              StartOfPeriod = gr.Key,Low = gr.Min(item => item.Low),High = gr.Max(item => item.High),Open = gr.OrderBy(item => item.TimeStamp).First().Open,Close = gr.OrderBy(item => item.TimeStamp).Last().Close
          });


public DateTime GetStartOfPeriodByMins(int numMinutes)
    {
        int oldMinutes = TimeStamp.Minute;
        int newMinutes = (oldMinutes / numMinutes) * numMinutes;

        DateTime startOfPeriod = new DateTime(TimeStamp.Year,TimeStamp.Month,TimeStamp.Day,TimeStamp.Hour,newMinutes,0);

        return startOfPeriod;
    }

解决方法

执行此操作的方法有很多,这取决于您需要多久读取一次数据,以及是否值得在每个滴答声中更新缓存,或者您需要一个计时器来保持数据刷新,或者您只想计算即时进行。

无论如何,我选择了一个队列来管理系列,我还选择了在每个刻度上(对或错)更新缓存。您可以轻松地使用列表,并实时进行过滤/查询,我将所有这些细节留给您。

给予

import { Child } from './child.entity';
  
  @Entity('attendances')
  export class Attendance extends BaseEntity {
    @PrimaryGeneratedColumn('increment',{ type: 'int' })
    id: number;

    @ManyToOne(type => Child,child => child.attendances)
    @JoinColumn({name: 'child_id'})
    child: Child;
    
    @Column('int')
    attendanceCd: number;
  
    @Column('time')
    comeHomeTime: Date;
  
    @Column('time')
    lateTime: Date;
  
    @Column('varchar')
    memo: string;
  
    @CreateDateColumn()
    createdAt: Date;
  
    @UpdateDateColumn()
    updatedAt: Date;
  
    @DeleteDateColumn()
    deletedAt: Date;
  }

保存它的字典

@Entity('children')
export class Child extends BaseEntity {
  @PrimaryGeneratedColumn('increment',{ type: 'int' })
  id: number;

  @Column('int')
  userId: number;

  @Column('varchar')
  moguPlusId: string;

  @Column('varchar')
  firstName: string;

  @Column('varchar',{ name: 'middle_name',nullable: true })
  middleName: string;

  @Column('varchar',{ name: 'last_name' })
  lastName: string;

  @Column('date')
  birthday: string;

  @Column('varchar')
  gender: string;

  @Column('varchar',{ name: 'blood_type' })
  bloodType: string;

  @Column('varchar',{ nullable: true })
  class: string;

  @Column('varchar',{ name: 'entrance_day',nullable: true })
  entranceDay: Date;

  @Column('int',{ name: 'is_active' })
  isActive: number;

  @CreateDateColumn({ name: 'created_at' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt: Date;

  @DeleteDateColumn({ name: 'deleted_at' })
  deletedAt?: Date;

  @OneToMany(type => Attendance,attendances => attendances.child)
  attendances: Attendance[];

  @ManyToOne(type => User,user => user.children)
  @JoinColumn({ name: 'user_id' })
  user: User;
}

用法

public class Tick
{
   public int Instrument { get; set; }
   public DateTime TimeStamp { get; set; }
   public decimal LatestPrice { get; set; }
}

public class Data
{
   private readonly Queue<Tick> _queue = new Queue<Tick>();
   public decimal High { get; private set; }
   public decimal Low { get; private set; }
   public decimal Open { get; private set; }
   public decimal Close { get; private set; }

   public void Add(Tick tick)
   {
      _queue.Enqueue(tick);
      Update();
   }

   public void Update()
   {
      var age = DateTime.Now.AddMinutes(-5);
      while (_queue.Any() && _queue.Peek().TimeStamp < age)
         _queue.Dequeue();

      High = _queue.Max(x => x.LatestPrice);
      Low = _queue.Min(x => x.LatestPrice);
      Open = _queue.LastOrDefault()?.LatestPrice ?? 0;
      Close = _queue.FirstOrDefault()?.LatestPrice ?? 0;

   }
}

如果您想即时进行计算

private Dictionary<int,Data> _instruments = new Dictionary<int,Data>();

注意:这并不是一个完整的解决方案,它缺乏健全性检查和一堆与您相关的详细信息。性能和效率也由您自行决定

,

编辑: 正如@Cid所提到的,第一种方法假定数据以固定的间隔出现,但很可能永远不会出现这种情况,并且很可能出错。最好的方法是尝试第二种方法,其中有两个变量并进行比较时间戳。


对此问题有多种解决方法。您提到每隔1秒获取一次数据,例如,您可以使用一个变量来计算收集到的数据量:

//before first element has come
int numberOfData=0;

然后每增加一个数字就增加numberOfData。当numberOfData为300(5 * 60s)时,假设您每秒获得数据的时间已经过去了五分钟。


另一种方法是,有两个变量firstData和lastData最初设置为null。然后为firstData分配第一个TickData,而不是仅比较firstData和即将到来的新TickData对象之间的时间戳。您可以在5分钟内将该对象分配给lastData。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。