Change chart to log chart C# - c#

Is it possible to change the scale of the y-axis on a chart to be logarithmic? I want to do it by clicking on a button even after the points have been plotted.
Here is the code for my scatterplot. The X value is the length of an array of numbers I am using in a bubble sort algorithm. The Y value comes from a stopwatch used to time how long the method takes to sort.
type = "bubble";
chart1.Series[type].Points.AddXY(dataArray.Length, sw.ElapsedMilliseconds);

Axis.IsLogarithmic sets a flag which indicates whether the axis is logarithmic. Zeros or negative data values are not allowed on logarithmic charts.
https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.axis.islogarithmic(v=vs.110).aspx
chart1.ChartAreas[0].AxisY.IsLogarithmic = true;

Related

I want Unity's slider value to handle large numbers precisely (it only works in the format of "xxx e+X")

I've been using Unity's slider to handle large numbers, and it accepts them. The problem is that the value stored is in the format "xxx e+X" (for instance, 9.999998e+08),
enter image description here
so, if I wanted to subtract one to this value, or add one to it, it doesn't change the value (for instance, the OnValueChanged callback doesn't get called) as it is only sensitive to larger steps (like, for example, changes over 50-100 units/integers and above.
Is there a way to make the slider work with long integers (plain number format)?
Thank you.
What I tried:
The slider max value is set to 999999799 (ended in 799). Then it translates into "9.999998e+08". if I convert this float value (9.999998e+08) to "long", I get 999999800, probably because it doesn't take into account small figures and goes by larger steps.
The only way that occurs to me to get the correct "long" is to convert the "slider max value" to string (string stringValue = _mySlider.value.ToString("F0")) and then get the "long" (long longValue= Convert.ToInt64(stringValue)). This way, I get the expected long (999999799).
However, this is not suitable since I cannot convert this long value into the slider value. If I wanted to subtract one from the long value (longValue--; (999999798)) and then set the slider value to the long value:
_mySlider.value = (float) longValue, the value of the slider doesn't change, it keeps being the same: 9.999998e+08. When translating the number, it yields 999999799 instead of 999999798. (Same happens if I did _mySlider.value--; directly)
I need the slider to handle large numbers too.

Modify code to get synthetic data that trends smoothly from bull to bear market cycles

I have this class that generates synthetic looking (stock) data and it works fine. However, I want to modify it so that NewPrice generates smooth trending data for say n-bars.
I know that if I reduce the volatility, I get smoother prices. However, not sure how to guarantee that the data goes into alternating persistant trend either up/down. A sine wave looking thing, but with stock looking prices, i.e, no negative prices.
Price = Trend + Previous Price + Random Component I am missing the trend component in the implementation below.
Any suggestions?
class SyntheticData
{
public static double previous = 1.0;
public static double NewPrice(double volatility, double rnd)
{
var change_percent = 2 * volatility * rnd;
if (change_percent > volatility)
change_percent -= (2 * volatility);
var change_amount = previous * change_percent;
var new_price = previous + change_amount;
previous = new_price;
return new_price;
}
}
Trade.previous = 100.0;
Price = Trade.NewPrice(.03, rnd.NextDouble()),
Exponential smoothing or exponential moving average will create the type of data you want. Ideally, you would have existing stock price data that represents the type of time series that you want to generate. You fit an exponential smoothing model to your data. This will determine a number of parameters for that model. You can then use the model and its parameters to generate similar time series with the same kind of trends, and you can control the volatility (standard deviation) of the random variable associated with the model.
As an example of what you can do, in the image below the blue and yellow parts are from real data, and the green part is synthetic data generated with a model that was fit to the real data.
Time series forecasting is a large topic. I do not know how familiar you are with that topic. See Time Series Analysis, it covers a large range of time series providing clear presentations and examples in Excel. See exponential smoothing for more theoretical background
Here is a specific example of how such a time series can be generated. I chose one of the 30 exponential smoothing models, one that has additive trend and volatility, and no seasonal component. The equations for generating the time series are:
The time index is t, an integer. The values of the time series are yt. lt and bt are respectively the offset and slope components of the time series. Alpha and beta are parameters, and l-1 and b-1 are initial values of the offset and slope components. et is the value of a random variable that follows some distribution, e.g. normal. Alpha and beta must satisfy the relations below for stability of the time series.
To generate different time series you choose values for alpha, beta, l-1, b-1, and the standard deviation of et assuming a normal law, and calculate the successive values of yt. I have done this in Excel for several combinations of values. Here are several time series generated with this model. Sigma is the standard deviation (volatility) of et.
Here are the equations for the 30 models. N means no trend / seasonal component. A means additive component. M means multiplicative component. The d subscript indicates a variant that is damped. You can get all of the details from the references above.
Something like this is what I was looking for:
public static double[] Sine(int n)
{
const int FS = 64; // sampling rate
return MathNet.Numerics.Generate.Sinusoidal(n, FS, 1.0, 20.0);
}
Although, it is not intuitive for a person that wants to deal in prices and time-based periodicity and not in mathematical functions.
https://numerics.mathdotnet.com/Generate.html

White Space in MS chart

I have a simple chart with 12 data points. The problem is that it shows a little white area before starting the trend lines.
Here is the code
for (int i = 0; i < 12; i++)
{
chart1.Series[0].Points.AddXY(DataTable.Rows[i].ItemArray[0], plotDataTable.Rows[i].ItemArray[1]);
chart1.Series[1].Points.AddXY(DataTable.Rows[i].ItemArray[0], plotDataTable.Rows[i].ItemArray[2]);
chart1.Series[2].Points.AddXY(DataTable.Rows[i].ItemArray[0], DataTable.Rows[i].ItemArray[3]);
chart1.Series[3].Points.AddXY(DataTable.Rows[i].ItemArray[0], DataTable.Rows[i].ItemArray[4]);
}
First column of DataTable is string and the other four are floats.
You need to set the AxisX.Minimum to a suitable value.
Usually this would be 0 or the x-value of the first DataPoint.
But the way you add the values this will not work.
You are adding the DataPoints in a rather unfortunte way, which sometimes is ok, but more often than not it will create all sorts of problems.
The recommended way is to add the x-values as numbers, or DateTimes, which internally will be converted to doubles.
But you add strings. This looks ok but the x-values contain neither those strings not anything else but 0s. Threfore you can't use them to set the range or tooltips or zoom ranges or to calculate stuff..
But if you want to you can still get the result you want by setting the minimum to 1:
ChartArea ca = yourChart.ChartAreas[0];
ca.AxisX.Minimum = 1;
I have added my x-values as string, too, but they look like numbers.
But the recommended way would be to convert your values to numbers so you can use them for all sorts of things..
A few notes:
This conversion is done by the chart, if at all possible for the y-values but not for the x-values! Maybe because a chart without numeric y-values makes no sense at all while sometimes x-values simply do not contain meaningful numeric data, like names, IDs, zip codes etc..
Don't let the visuals fool you: The strings are only copied into the axis labels; otherwise they are lost! (You should check this with the debugger!!)
You may notice that the number of Label changes in the screenshot. The number is calculated from the Interval of the x-axis. By default it is calculated automatically (Interval=double.NaN)to fit in a reasonable number. You can set it to any distance you like. Normaly it refers to the axis unit but in this case to the number of points. Set it to 2 to get one Label for every 2nd point; set it to 0.5 to get 2 Labels per DataPoint..
With real numbers (or DataTimes) as x-values you can also set a type for the interval like seconds or days..
By default, the ChartArea's IsStartedFromZero property is set true. This setting will force the chart to always start from zero. Try setting it to false:
chart1.ChartAreas[0].AxisX.IsStartedFromZero = false;
chart1.ChartAreas[0].AxisY.IsStartedFromZero = false;

Get Points of Intersection with Sine Wave

I have a particle at a fixed position X and fixed amplitude AMP that travels on a sin wave.
I'd like to be able to dynamically change the period of the target sine wave WITHOUT moving the particle. (When I change the period, its X position doesn't line up to the same Y position of the graph with a different period, so it jumps all over the place.
I have a solution for this - Find where the graph with the new period intersects with the graph of the old period and create an X-offset, lining these two figures up.
For any given y on a sin wave, there will be 2 corresponding X values per period. I'm trying to get these two values. I'll then compare the derivatives to choose which one I want.
However, I don't know how to get both of these values. Any ideas?
Here's an image of what I'm after: Sin Wave Logic
If you have a sine-wave defined by
y = sin(a*(x+c))+d
then you can reverse it by
x = (arcsin(y-d)-c)/a
for a given a.
This yields the solution in the range of [-pi;pi]
The other solution you are looking for is then 2*pi-x
If you allow a little cheating, you can use a cross-fading effect to get a smooth transition from f(t) to g(t) via
h(s,t)=(1-s)*f(t)+s*g(t)
while s as a function of t is between 0 and 1 and use something like
y = h( (t-ts)/d, t)
for the time period from ts to ts+d.

Auto-Interval precision in MS Chart

I'm currently using the charting within .NET using System.Windows.Forms.DataVisualization.Charting.Chart. Thus far it seems very powerful, and works great. However, there is a huge problem in terms of how it is auto-calculating intervals. I use a lot of double values, and in libraries like ZedGraph, it handles this perfectly. It selects min/max/interval just fine. However, in MS Chart, it may select 206.3334539832 as a minimum, and intervals of a similar decimal precision. Obviously this looks quite ugly.
So, I tried simply making the axis format {0.00} and it works great when it loads the chart. Except when you zoom in, you need greater precision, maybe at 4 decimal places instead of 2. It seems I'm either stuck with 9 decimal places all the time, or else a constant fixed number that may break when someone requires greater precision. I'd rather it pick up the precision based on the level of zoom currently applied. Libraries like ZedGraph and Dundas (which I believe MS is even using!) tend to pick good values that change as you zoom in and out.
Is there any way to have the intervals change precision as the zoom frame changes? It's probably some simple property I have set wrong, but it's hard to tell with the millions of properties this thing has (especially when there's about 14 places that represent the concept of Interval).
I had the exact same problem when zooming. I added code to format the axis labels and call it from the Paint handler. The Axis View objects have an IsZoomed property and have functions to get the current axis limits (GetViewMinimum/Maximum). I set the Axis LabelStyle.Format to "N" for all cases unless the Max-Min=range is less than 1. Then I set the format to "F#" where # is calculated based on the axis range.
# = Convert.ToInt32(Math.Abs(Math.Log10(range) - .5)) + 1;
Having played around with the chart control I haven't been able to find a simple solution to your problem. However the following may help:
Have you considered setting the maximum and minimum values for the axes yourself? If you round the actual maximum and minimum values to the nearest sensible "round" number (5, 10, 0.5, 0.01) this should make the calculated intervals a bit more friendly.
I understand this is not an ideal solution but by carefully choosing the maximum and/or minimum values you can ensure the intervals are "nicer" numbers. If the range of your axes is say divisible by 2, 5 & 10 it should result in fairly nice intervals.
Why not modify number format string.
Create format string
string formatString = "{0.00";
Identify zoom level, say zoomLevel = 2;
formatString = formatString.PadRight(5+zoomLevel, '0');
formatString += "}";
Now use this format on axis legend. Use string builder or some better way to modify the format string.
To provide the result with minimal cost you can use exponential scientific format
You can attach to customize event.
From there, you can modify the labels on x-axis:
var xAxisLabels = chart1.ChartAreas[0].AxisX.CustomLabels;
...
xAxisLabels[0].Text = ...
set min. and max. values:
chart1.ChartAreas[0].AxisX.Maximum = ...;
etc.
you can dynamically update the max and min based on your data set. each time user zooms in, you do a FOREACH on every point and get the stats and based on that set your max and min
It helps to set the IntervalOffset of the axis, here an example:
Private Sub chMap_AxisViewChanged(sender As System.Object, e As System.Windows.Forms.DataVisualization.Charting.ViewEventArgs) Handles chMap.AxisViewChanged
'the grid ticks are rounded values
e.Axis.IntervalOffset = -e.Axis.ScaleView.ViewMinimum
End Sub

Categories

Resources