I'm trying to build stock market Bar (snapshot) data at run-time using tick data. My stock data provider provides access to tick level data where I have an event called OnTick that is triggered whenever a new tick is sent by the data provider. I'm hoping to do one of the two below, or if someone can suggest a good option:
Option 1:
In this option I maintain a Bar object and update it each time I get a tick. The OnBar() event can be attached to a timer elapsed event (1 minute for 1 minute bars etc).
//TickMsg = double price, DateTime dttm
public void OnTick(TickMsg newTick)
{
TaskFactory.StartNew(){UpdateBar(newTick)};//Syntax not specific
}
UpdateBar()
{
//nextBar is a Bar object thats intialized to Open = 0, High = 0, Low = 0, Close = 0
if(nextBar.Open==0)
nextBar.Open = newTick.price;
if(newTick.price>nextBar.High)
nextBar.High = newTick.price;
if(newTick.price<nextBar.Low)
nextBar.Low = newTick.price;
nextBar.Close = newTick.price;
}
public void OnBar(Bar bar)
{
//Process the bar..perform calculations etc
bar = new Bar(0,0,0,0);//Reset the bar
}
Option 2:
In this option I'm just adding the tick to a list of ticks and perform the calculations when OnBar is called. The OnBar() event can be attached to a timer elapsed event (1 minute for 1 minute bars etc).
List <TickMsg> TickList;
public void OnTick(TickMsg newTick)
{
TickList.Add(newTick);
}
public void OnBar()//called on a timer
{
var low = TickList.Min();
var high = TickList.Max();
var close = (from entry in TickList orderby entry.TickMsg.dttm ascending).Last();
var open = (from entry in TickList orderby entry.TickMsg.dttm ascending).First();
TickList.Empty();
}
Questions:
Which approach is more processing intensive?
Which approach requires more memory?
Again, if someone has a suggestion on an alternative approach, I'm all ears.
Don't you need to display or access the bar before it's completed? In case option 2 seems not to achieve that. Option 1 I can never imagine will be a performance clog. And it will use less memory, as you don't seem to save the tick data to any variable.
I think the best approach it is the second.
When you reset the bar on first approach, the lowest price will never be less than zero, so, the low price on bar will be always zero.
Trade link is a good example on how it is done. Their tutorials cover this. Also since it is open source you can have a peek into how it is done. The getting started tutorial is here.
Related
I've created a simple DateTime array that contains 3 items. These items are set to use the values of three different DateTimePickers on my form. Before I go further into using the array, I need to make sure it is actually using the correct values, and it does not appear to be doing so. Here's my code:
namespace Test
{
public partial class Form1 : Form
{
DateTime[] monSchedule = new DateTime[3];
public Form1()
{
InitializeComponent();
monSchedule[0] = monStart.Value;
monSchedule[1] = monEnd.Value;
monSchedule[2] = monLunch.Value;
}
private void Form1_Load(object sender, EventArgs e)
{
setDefaults();
}
private void setDefaults()
{
monStart.Value = DateTime.Parse("00:00");
monEnd.Value = DateTime.Parse("00:00");
monLunch.Value = DateTime.Parse("00:00");
}
private void validate()
{
MessageBox.Show("You entered time " + monSchedule[0]);
}
When I load my form, setDefaults(); should change the values to the current date with a time of 00:00. When I press the button to show the value in the array, it is pulling current date and current time. I need it to pull whatever the current time in that DateTimePicker is. So if a user types 10:00 into the DateTimePicker (they are formatted HH:mm), then I need the MessageBox to say the time is 10:00 AM. If I change the value to 22:00, then I need the messagebox to say the time is 10:00 PM. etc. (Date is irrelevant in my scenario, I'm not concerned with what the date is at all. Only the time.)
I suspect it may be because of the order it's written in. Is the array storing the value of the DateTimePicker BEFORE setDefaults(); is run? If so, how do I make the values of the array items dynamic since the values of the DateTimePickers are going to change a lot and I need the array elements to be updating with the latest values?
EXTRA INFO:
-Using Visual Studio
-Added the DateTimePickers in design view, changed the format to HH:mm there, did not change the default values in design view
-Ignoring date completely, only concerned with time right now
PS: I was also struggling with where to declare the array so it was accessible in multiple other methods and found I had to declare the array initializer within public partial class Form1, but then add the items in the array within public Form1(), because it wouldn't let me add them under public partial class Form1. I don't know if this is correct though, but it seemed to work when I tested with an array of strings so I went with it.
I have to say that this is a bit of a regression. In your previous question, JoshPart gave you good advice in the form of user controls, although he may have left some gaps too large for you to fill on your own.
Using arrays in this manner might work for a single day, but it won't scale well to a full week.
In case anyone reading this is wondering why I'm talking about a full week, I refer you to the previous question. Also, I recognize that I'm going off-topic for this specific question but I believe this to be an XY problem and the previous question was actually based on the real problem and work that was more on-the-mark.
Let's start with what we know. I've gleaned this from the two questions and the various comments in both.
You have DateTimePicker controls for start, end, and lunch. You're only interested in the time portion so you have Format set to "Custom" and CustomFormat set to "HH:mm". Assumption: lunch is a fixed length so the end time isn't needed.
You have the aforementioned controls times seven, one set for each day of the week.
You've written validation code (range tests) to determine if values are entered correctly, and you're able to show a label with red exclamation marks when that test fails.
You've identified that it's getting too complicated just having a bunch of controls on a form.
So far, so good. Now for your goal.
You're looking for a way to organize the controls, and the data they collect, to make it easier to work with them.
A user control is still the way to go here. You'll benefit from encapsulating all that repeated functionality into a single place and being able to reuse it.
Start by creating a user control -- we'll call it DayPanel -- and put all the controls for a single day on that canvas. Name the controls without any regard for the day of week (e.g. start, lunch, and end). Your user control will neither know nor care which day it represents.
Add an event handler for the ValueChanged event to the DateTimePicker controls. Instead of double-clicking the control, go to the events list in the Properties tool window and type a name, such as the one below, for the ValueChanged event. Do the same for the other two controls and it will reuse the event handler that it created the first time. Whenever the user changes a time, this event handler will be called and it will effect changes to the UI.
private void picker_ValueChanged(object sender, EventArgs e)
{
// In case you need to know which DateTimePicker was changed, take a look at 'sender':
//DateTimePicker picker = (DateTimePicker)sender;
UpdateWarningState();
}
As Jimi mentioned, the sender object will be a reference to the DateTimePicker control that sent the event. You probably won't need it but it's there if you do.
UpdateWarningState just hides/shows the warning label based on the validity of the inputs.
private void UpdateWarningState()
{
warningLabel.Visible = !IsInputValid(start.Value.TimeOfDay, lunch.Value.TimeOfDay, end.Value.TimeOfDay);
}
I had suggested in comments on the previous question that it seemed to make sense to get true if the inputs are valid and then use the logical negative for the visibility of the warning label.
As Paul Hebert pointed out, you really only need to compare a TimeSpan, so IsInputValid receives the TimeOfDay property to deal with only that much.
private bool IsInputValid(TimeSpan startTime, TimeSpan lunchTime, TimeSpan endTime)
{
return startTime < lunchTime && lunchTime.Add(TimeSpan.FromMinutes(30)) < endTime;
}
In fact, even though you're only inputting a time, the control still returns a date part in its Value property. If you want to be certain that you're not comparing times in different dates, you'll definitely need to use the TimeOfDay property. That said, by not presenting the date part, you have a measure of control over that so it's not a pressing concern. If you had to worry about crossing over midnight, that would complicate things.
Note that I've dealt with that earlier assumption that lunch is a fixed length by adding 30 minutes in the comparison to the end time.
Why not just do all that in the ValueChanged event handler?
The Single Responsibility Principle. IsInputValid does one thing: business logic; it tells you if the inputs are valid based on range testing. UpdateWarningState does a different thing: UI logic; it updates the visibility of warning label based on the validity of the inputs.
UpdateWarningState is reusable. You can call it from other event handlers in the future. Event handlers really shouldn't ever do much. They're more like telephone operators: "how may I direct your call?"
IsInputValid is reusable. The business logic can be extracted from your UI code at some point in the future and be reused by something else. I'll admit that the name leaves something to be desired; it fits here but probably should be different outside this context.
But what good is this user control if you have no way of working with its data? The consumer needs to be able to interact with it. A user control is just another class so you can define public properties, methods, and events as you see fit. We'll add properties for the three values of interest:
public TimeSpan Start
{
get => start.Value.TimeOfDay;
set => start.Value = start.Value.Date + value;
}
public TimeSpan Lunch
{
get => lunch.Value.TimeOfDay;
set => lunch.Value = lunch.Value.Date + value;
}
public TimeSpan End
{
get => end.Value.TimeOfDay;
set => end.Value = end.Value.Date + value;
}
What's interesting to note about these properties is that they don't have their own backing storage. Instead, they defer to the controls and translate between their own TimeSpan data type and the controls' DateTime data type. On get, they return just the TimeOfDay property. On set, they remove the time portion (with .Date) and add the time of day.
If you were building this for someone else to consume, you'd want to ensure that the Days property is 0 and that the whole value is non-negative, and either throw ArgumentOutOfRangeException or (gasp!) clamp the value to the acceptable range.
Now that you have a functioning control for a single day, you can slap a bunch of them on the main form. Back in Form1, add seven instances of the DayPanel control and name them monday through sunday. Before we get to initialization, let's create a lookup for these user controls.
private readonly Dictionary<DayOfWeek, DayPanel> _dayPanelLookup;
public Form1()
{
InitializeComponent();
_dayPanelLookup = new Dictionary<DayOfWeek, DayPanel>()
{
[DayOfWeek.Monday] = monday,
[DayOfWeek.Tuesday] = tuesday,
[DayOfWeek.Wednesday] = wednesday,
[DayOfWeek.Thursday] = thursday,
[DayOfWeek.Friday] = friday,
[DayOfWeek.Saturday] = saturday,
[DayOfWeek.Sunday] = sunday
};
}
Now the Load handler can then initialize all the properties. This DefaultTime duplicates the TimeSpan.Zero constant for the purpose of giving it a distinct meaning and can help with refactoring later on.
private static readonly TimeSpan DefaultTime = TimeSpan.Zero;
private void Form1_Load(object sender, EventArgs e)
{
SetDefaults();
}
private void SetDefaults()
{
foreach (DayPanel dayPanel in _dayPanelLookup.Values)
{
dayPanel.Start = DefaultTime;
dayPanel.Lunch = DefaultTime;
dayPanel.End = DefaultTime;
}
}
And just for fun, we can use _dayPanelLookup to grab one of them based on a variable containing the day of the week.
public void someButton_Click(object sender,
{
DayOfWeek whichDay = SelectADay();
DayPanel dayPanel = _dayPanelLookup[whichDay];
// ...
}
That should address the main concern of organizing the controls and making it easy to work with them and their values. What you do with it once the user presses some as-yet-unidentified button on the form is a whole new adventure.
There are yet better ways of doing all of this, I'm sure. I'm not a UI developer, I just play one on TV. For your purposes, I hope this not only gives you the guidance you needed at this point in this project but also illuminates new avenues of thought about how to structure your programs in the future.
It is unclear what you want the date component of the date part of DateTime to be DateTime.Parse("00:00") should return midnight today or 12/27/18 12:00:00 AM;
This is also the same value as DateTime.Today
In addition, you can create a new DateTime with a constructor
monStart.Value = new DateTime(2018, 12, 27, 0, 0, 0);
This is midnight the today
Note:
Reading the description in your updated question, it appears that the DateTimePicker controls values are accessed on a Button Click. If this is the actual scenario, you probably don't need a DateTime array field at all: you could just read the values directly from the DTP controls and use the values in-place.
The example assumes (to comply with the question) that you need that array anyway.
A possible way to proceed:
Set the default values in the Form.Load event. Initialize the monSchedule array values right after, so the values are synchronized. Note that the Form.Load event handler code is (of course) executed after the class constructor (public Form1() { }): the Form object must be already initialized.
Assign an event handler to all the DateTimePicker controls (same event for all). The event handler is used to assign the new values to the monSchedule array. The event could be the ValueChanged event or, possibly, the more generic Validating event. The former is raised each time you change any part of the Time value (the hour value or minutes value). The latter only when the control loses the focus. Your choice.
Use the sender object in the event handler to determine which control raised the event and update the corresponding array value.
An example, using a switch statement and a case statement with a when clause:
Notes:
1. You need C# 7.0+ to use this switch syntax. Otherwise, you could switch using a Type pattern (see the Docs) or the DateTimePicker name (see the example).
2. The DTP_ValueChanged(object sender, EventArgs e) event (the ValueChanged handler) is assigned to all the DateTimePicker controls.
public partial class Form1 : Form
{
DateTime[] monSchedule = new DateTime[3];
private void Form1_Load(object sender, EventArgs e)
{
SetDefaultDTPValues();
}
private void SetDefaultDTPValues()
{
monStart.Value = DateTime.Parse("00:00");
monEnd.Value = DateTime.Parse("00:00");
monLunch.Value = DateTime.Parse("00:00");
monSchedule[0] = monStart.Value;
monSchedule[1] = monEnd.Value;
monSchedule[2] = monLunch.Value;
}
private void DTP_ValueChanged(object sender, EventArgs e)
{
switch (sender)
{
case DateTimePicker dtp when dtp.Equals(monStart):
monSchedule[0] = dtp.Value;
break;
case DateTimePicker dtp when dtp.Equals(monEnd):
monSchedule[1] = dtp.Value;
break;
case DateTimePicker dtp when dtp.Equals(monLunch):
monSchedule[2] = dtp.Value;
break;
}
}
}
On a Button.Click event:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show($"Start: {monSchedule[0].ToString("hh:mm tt")} " +
$"End: {monSchedule[1].ToString("hh:mm tt")} " +
$"Lunch: {monSchedule[2].ToString("hh:mm tt")}");
}
If the C# version in use doesn't allow this switch statement syntax, you can use the DateTimePicker name instead (there are other options, see the examples in the Docs):
private void DTP_ValueChanged(object sender, EventArgs e)
{
DateTimePicker dtp = sender as DateTimePicker;
switch (dtp.Name)
{
case "monStart":
monSchedule[0] = dtp.Value;
break;
case "monEnd":
monSchedule[1] = dtp.Value;
break;
case "monLunch":
monSchedule[2] = dtp.Value;
break;
}
}
I have a ICollectionVIew named 'CompanyView'.
I also have a Filter for it called 'CompanyFilter'.
And a Textbox bound to a 'SearchCompanyTitle' property.
As I type in a databound textbox, 'CompanyFilter' gets fired with every letter and the 'CompanyView' gets filtered to show relevant results.
That works fine.
Unfortunately the table I'm filtering has about 9 000 rows so there tends to be a notable delay between the moment you press the key on the keyboard and it showing up on screen.
So what I decided to do instead was ensure that the filter was automatically fired when the user had finished typing. Which raises the question of how does the ViewModel know when the user has finished?
What I did is the below;
// This is the property the Textbox is bound to
private string _searchCompanyTitle = "";
public string SearchCompanyTitle
{
get { return _searchCompanyTitle; }
set
{
_searchCompanyTitle = value;
OnPropertyChanged("SearchCompanyTitle");
// After a character has been typed it will fire the below method
SearchCompany();
}
}
// This method is fired by the above property everytime a character is typed into the textbox
// What this method is meant to do is wait 1000 microseconds before it fires the filter
// However I need the timer to be reset every time a character is typed,
// Even if it hasn't reached 1000 yet
// But it doesn't do that. It continues to count before triggering the filter
private async void SearchCompany()
{
bool wait = true;
while (wait == true)
{
await Task.Delay(1000);
wait = false;
}
CompanyView.Filter = CompanyFilter;
}
// And this is the filter
private bool CompanyFilter(object item)
{
company company = item as company;
return company.title.Contains(SearchCompanyTitle);
}
So that's my problem. I need the filter to fire only when the timer hits 1000 and not before. At the same time I need the timer to go back to 0 every time the method is fired by the property. Clearly I'm not doing it right. Any ideas?
Sounds like a perfect candidate for binding Delay:
<TextBox Text="{Binding SearchCompanyTitle, Delay=1000}"/>
One solution could be to use the System.Threading.Timer class.
You can give it a callback to be called when the time set is elapsed.
Put the filter method as the callback and reset the timer's time on every key stroke.
You can find an example here.
--EDIT--
I didn't see that you were using WPF, Sinatr answer is the correct one, just use binding delay
I am taking over a C# code from someone who implemented a desktop application to read real time data from the Serial Port and displaying it in charts (using the Chart Class).
The code seems to be working, but is very slow. It seems to be updating the chart around once in 4 seconds (0.25Hz). However, I can see that it is multi-threaded and has no delay commands, so I don't understand why it is running so slow. Could the updating of charts slow it down? Ideally I would like to achieve 1000 data points per second (1kHz), displaying it in real time and saving it to the hard disk, where the size of each data point is about 30 bytes.
I spent few days understanding the code, but it's too cumbersome to follow, all written in a single file, with no comments. Is my goal of reading 1000 data points per second realistic/achievable?
I'm also considering to re-write the code (as opposed to trying to fix it), considering it's only about 2,500 lines long. Any tips would be appreciated. Also, if I rewrite the code, what language might be better for this application?
I developed some code where I got significant performance improvement, it may work for you. Here is what I did-
Step 1: I would first identify, which one is the bottle neck, drawing/rendering of the chart
or serial port
Step 2: If you find its the rendering-- then add this in your form/chart setup, it will draw much faster. But first double check to make sure you're not in remote desktop mode.
<!-- language: c# -->
// No double buffering for remote, only local
public bool OptimizeOfLocalFormsOnly(System.Windows.Forms.Control chartControlForm)
{
if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
{
SetUpDoubleBuffer(chartControlForm);
return true;
}
return false;
}
public static void SetUpDoubleBuffer(System.Windows.Forms.Control chartControlForm)
{
System.Reflection.PropertyInfo formProp =
typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
formProp.SetValue(chartControlForm, true, null);
}
I assume you using winform application :
Use serialPort component :
Configure its properties : (BaudRate, DataBits, StopBits, Parity ...)
Make use of its event (DataReceived) to collect your inputs.
You can send commands in a loop and collect the inputs/drawing them on chart component roughly like :
while(/*some condition*/)
{
serialPort.Write(/* your command */);
// you have to think of response time
// so implement something that waits a bit before calling the port again
// I would do it using timers
int tick= Environment.TickCount;
while(Environment.TickCount - tick <= 100) // wait 100 milliseconds
{
Application.DoEvents();
}
}
// collect the data as:
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// use according to your needs, for example
string data = "";
int readByte;
int available;
available = serialPort.BytesToRead;
if(available >= 30) // 30 bytes as stated in your question
{
for(int i=0; i<30; i++)
{
readByte = serialPort.ReadByte();
data += String.Format("{0:2X}", readByte);
}
// you can call some methods to save/display your collected data from here
save_to_file(data);
display_to_chart(data);
}
}
I developed a similar app where I was displaying 16charts * 256 samples/sec. Storing the data in a buffer and creating a separate thread for updating the charts worked for me.
When new data is read, data is stored in a list or array. Since it is real-time data, the timestamps are also generated here. Using the sample rate of the data acquired: timeStamp = timeStamp + sampleIdx/sampleRate;
public void OnDataRead(object source, EEGEventArgs e)
{
if ((e.rawData.Length > 0) && (!_shouldStop))
{
lock (_bufferRawData)
{
for (int sampleIdx = 0; sampleIdx < e.rawData.Length; sampleIdx++)
{
// Append data
_bufferRawData.Add(e.rawData[sampleIdx]);
// Calculate corresponding timestamp
secondsToAdd = (float) sampleIdx/e.sampleRate;
// Append corresponding timestamp
_bufferXValues.Add( e.timeStamp.AddSeconds(secondsToAdd));
}
}
Then, create a thread that sleeps every N ms (100ms is suitable for me for a 2 seconds display of data, but if I wanna display 10 seconds, I need to increase to 500ms of sleep time for the thread)
//Create thread
//define a thread to add values into chart
ThreadStart addDataThreadObj = new ThreadStart(AddDataThreadLoop);
_addDataRunner = new Thread(addDataThreadObj);
addDataDel += new AddDataDelegate(AddData);
//Start thread
_addDataRunner.Start();
And finally, update the charts and make the thread sleep every N ms
private void AddDataThreadLoop()
{
while (!_shouldStop)
{
chChannels[1].Invoke(addDataDel);
// Sleeep thread for 100ms
Thread.Sleep(100);
}
}
The AddData method, simply reads the X (timestamp) and Y values stored in the buffer and add its to the charts using ptSeries.Points.AddXY(xValue, yValue)
My app needs to display the process time of some operations. One of the process times is the time spent to refresh the proces times at the UI ( got it? :D ).
The frequency of the operations can vary from 0 to about 100 Hz (10 ms).
The process times are display in some labels. To set it values I use this static method:
public Class UserInteface
{
//Static action to SafeSetControlText
private static Action<Control, string> actionSetControlText = delegate(Control c, string txt) { c.Text = txt; };
//Control
//Set Text
public static void SafeSetControlText(Control control, string text, bool useInvoke = false)
{
//Should I use actionSetControlText or it is ok to create the delegate every time?
Action<Control, string> action = delegate(Control c, string txt) { c.Text = txt; };
if (control.InvokeRequired)
{
if (useInvoke)
control.Invoke(action, new object[] { control, text });
else
control.BeginInvoke(action, new object[] { control, text });
}
else
action(control, text);
}
}
Questions:
I dont want to freeze all my UI tryng to update the process times, so how should I control when is it ok to refresh? Now Im doing something like: only update if last update time was 100 ms before now.
If I use BegingInvoke, is it possible to overflow the queues with too much calls?
How can I measure the UI refresh time using BeginInvoke? The best way is to use Invoke?
Pretty acceptable solution, by me, cause if you do not control it, it can result on data blinking on UI side.
No, I don't think you can overflow, especially on 10 ms, speed.
If you want to be sure on time measuring (as much as it possible) the solution is definitely is using of Invokde. The same ou an use also in production.
But this is something you gonna to measure against your specific application requirements.
I'm Doing a project on FileTransfer in which i have a listview , i will get events from one of my class file for updating the percentage of the file sent so far,after receiving it i will place the percentage in my listview ,while doing that the listview got
a flickering effect how to avoid it.i used application.doevents() but it doesnt works. i have seen in torrents while updating the percent the list doesnt get flickered
how to achieve this .
void Sender_Progress(int CurrentValue, string Ip) // here im receiving Events
{
try
{
//if (CurrentValue == 1)
// UpdateTimer.Enabled = true;
//list_send.Items[CurrentValue].SubItems[4].Text = Ip.ToString();
//Application.DoEvents();
obj = new object[] {CurrentValue, Ip };
list_send.Invoke(new UpdateList(UpList), obj);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void UpList(int Val, string ind) // here im updating the listview
{
Application.DoEvents();
int index = 0;
index = Convert.ToInt32(ind);
index = index - 1;
list_send.Items[index].SubItems[4].Text = Val.ToString();
if (Val == 100)
{
list_send.Items[index].SubItems[2].Text = "Completed.";
//UpdateTimer.Enabled = false;
}
//Application.DoEvents();
}
Firstly, you don't need the DoEvents, since you are already correctly working on two threads. Remove that. After that, I expect the problem is simply doing too much too quickly. Is it possible to batch updates, and only send an update, say, every 20? 50? times? It isn't clear what the control is, but many have multiple-update modes; for example with ListView:
theList.BeginUpdate();
try {
// make multiple updates here...
} finally {
theList.EndUpdate();
}
I would then see about passing over a list of updates, say, every 20 times (unless each takes a considerable time) [note it must be a different list per Invoke, and you need to remember to send any remaining items at the end, too].
Use worker thread - it's available from the toolbox and has two events that are invoked in the main (UI) thread.
The Progress event can be used to signal the listbox that it need to refresh or that the task was completed.
i overcome the flickering effect succesfully,im getting events frequently ,i will get an integer everytime, i will store it in a variable and compare it with next variable received by the event if it matches i wont invoke the listview,otherwise i will invoke it.now the flickering goes away. thanks all.