Protobuf doesn't support multi-dim arrays so I decided to use this implementation to make a 1D array out of a 2D one.
I get a Cannot cast from source type to destination type in the ToProtoArray method when I call the MultiLoop function. Any ideas on how to fix this?
public static ProtoArray<T> ToProtoArray<T>(this System.Array array)
{
// Copy dimensions (to be used for reconstruction).
var dims = new int[array.Rank];
for (int i = 0; i < array.Rank; i++) dims[i] = array.GetLength(i);
// Copy the underlying data.
var data = new T[array.Length];
var k = 0;
array.MultiLoop(indices => data[k++] = (T)array.GetValue(indices));
// ^^^^^^^^^^ cannot cast from source type to destination type
return new ProtoArray<T> { Dimensions = dims, Data = data };
}
public static System.Array ToArray<T>(this ProtoArray<T> protoArray)
{
// Initialize array dynamically.
var result = System.Array.CreateInstance(typeof(T), protoArray.Dimensions);
// Copy the underlying data.
var k = 0;
result.MultiLoop(indices => result.SetValue(protoArray.Data[k++], indices));
return result;
}
public static void MultiLoop(this System.Array array, System.Action<int[]> action)
{
array.RecursiveLoop(0, new int[array.Rank], action);
}
private static void RecursiveLoop(this System.Array array, int level, int[] indices, System.Action<int[]> action)
{
if (level == array.Rank)
{
action(indices);
}
else
{
for (indices[level] = 0; indices[level] < array.GetLength(level); indices[level]++)
{
RecursiveLoop(array, level + 1, indices, action);
}
}
}
[ProtoContract]
public class ProtoArray<T>
{
[ProtoMember(1)]
public int[] Dimensions { get; set; }
[ProtoMember(2)]
public T[] Data { get; set; }
}
Here's how I use this to serialize a 2D array:
[ProtoContract]
public class Tile
{
[ProtoMember(1)]
public int x;
[ProtoMember(2)]
public int y;
// ...
}
Tile[,] map; // meanwhile I assign the data to the array
map1d = Extensions.ToProtoArray<Tile[,]>(map);
using (var file = File.Create(path))
{
Serializer.Serialize(file, map1d);
}
I think this is what you need:
public class ProtoArray<T>
{
public ProtoArray(T[] array)
{
this.Data=array;
this.Dimensions=new int[array.Length];
}
public ProtoArray(T[,] array)
{
int n = array.GetLength(0);
int m = array.GetLength(1);
this.Data=new T[n*m];
for(int i = 0; i<n; i++)
{
for(int j = 0; j<m; j++)
{
// Row Major
Data[i*m+j]=array[i, j];
// For Column Major use Data[i+j*n]=array[i, j];
}
}
this.Dimensions=new[] { n, m };
}
public int[] Dimensions { get; set; }
public T[] Data { get; set; }
public T[] ToArray()
{
if(Dimensions.Length==1)
{
return Data.Clone() as T[];
}
else
{
throw new NotSupportedException();
}
}
public T[,] ToArray2()
{
if(Dimensions.Length==2)
{
int n = Dimensions[0], m = Dimensions[1];
T[,] array = new T[n, m];
for(int i = 0; i<n; i++)
{
for(int j = 0; j<m; j++)
{
array[i, j]=Data[i*m+j];
}
}
return array;
}
else
{
throw new NotSupportedException();
}
}
}
public class Tile
{
public int x;
public int y;
// ...
}
class Program
{
static void Main(string[] args)
{
Tile[,] map = new Tile[16, 4];
ProtoArray<Tile> array = new ProtoArray<Tile>(map);
//serialize array
//
// de-serialize array
Tile[,] serialized_map = array.ToArray2();
}
}
I get the error converting Int to Double, my next line Average[y] = Average[y] + Students[i].Marks; is not working either. So how can convert int[] to double[]?
public static double[] Averages(StudentMarks[] Students, int amount, string[] DifferentGroups, int GroupAmount, out double[] Average)
{
Average = new double[Max];
int y = 0;
int CountGroups = 0;
//int sum = 0;
for (int i = 0; i < amount; i++)
{
if (Students[i].Group == DifferentGroups[y])
{
Convert.ToDouble(Students[i].Marks);
//Average[y] = Average[y] + Students[i].Marks;
}
}
return Average;
}
The main:
static void Main(string[] args)
{
int amount;
StudentMarks[] Students;
string[] DifferentGroups;
int GroupAmount;
double[] Average;
ReadData(out Students, out amount);
DifferentGroups = FindDifferentGroups(Students, amount, out DifferentGroups, out GroupAmount);
Average = Averages(Students, amount, DifferentGroups, GroupAmount, out Average);
Class:
public const int Max = 50;
public string Surname { get; set; }
public string Name { get; set; }
public string Group { get; set; }
public int AmountOfMarks { get; set; }
public int[] Marks { get; set; }
So Student[i].Marks is Array.
Convert.ToDouble returns a double - it does not make an integer property or variable a double.
I think you want:
if (Students[i].Group == DifferentGroups[y])
{
double mark = Convert.ToDouble(Students[i].Marks);
Average[y] = Average[y] + mark;
}
or just:
if (Students[i].Group == DifferentGroups[y])
{
Average[y] = Average[y] + Convert.ToDouble(Students[i].Marks);
}
All Convert.ToXXX functions return the new value. Therefore, you should be expecting that and assigning the return value to a local variable.
Something like:
double YourMark = Convert.ToDouble(Students[i].Marks);
So how can convert int[] to double[]?
By programming. You write code to do it.
var d = new double[Students[i].Marks.Length];
for (int j = 0; j < Students[i].Marks.Length; ++j)
{
d[j] = Convert.ToDouble(Students[i].Marks[j]);
}
Or use LINQ:
var d = Students[i].Marks.Select(n => Convert.ToDouble(n)).ToArray();
Next time a method call won't compile or doesn't work the way you hoped it might, a good first step would be to check the documentation.
I'm trying to build a class to create Aroon series. But it seems I don't understand the steps well. I'm not sure about for what purpose I have to use the period parameter.
Here is my first attempt:
/// <summary>
/// Aroon
/// </summary>
public class Aroon : IndicatorCalculatorBase
{
public override List<Ohlc> OhlcList { get; set; }
public int Period { get; set; }
public Aroon(int period)
{
this.Period = period;
}
/// <summary>
/// Aroon up: {((number of periods) - (number of periods since highest high)) / (number of periods)} x 100
/// Aroon down: {((number of periods) - (number of periods since lowest low)) / (number of periods)} x 100
/// </summary>
/// <see cref="http://www.investopedia.com/ask/answers/112814/what-aroon-indicator-formula-and-how-indicator-calculated.asp"/>
/// <returns></returns>
public override IIndicatorSerie Calculate()
{
AroonSerie aroonSerie = new AroonSerie();
int indexToProcess = 0;
while (indexToProcess < this.OhlcList.Count)
{
List<Ohlc> tempOhlc = this.OhlcList.Skip(indexToProcess).Take(Period).ToList();
indexToProcess += tempOhlc.Count;
for (int i = 0; i < tempOhlc.Count; i++)
{
int highestHighIndex = 0, lowestLowIndex = 0;
double highestHigh = tempOhlc.Min(x => x.High), lowestLow = tempOhlc.Max(x => x.Low);
for (int j = 0; j < i; j++)
{
if (tempOhlc[j].High > highestHigh)
{
highestHighIndex = j;
highestHigh = tempOhlc[j].High;
}
if (tempOhlc[j].Low < lowestLow)
{
lowestLowIndex = j;
lowestLow = tempOhlc[j].Low;
}
}
int up = ((this.Period - (i - highestHighIndex)) / this.Period) * 100;
aroonSerie.Up.Add(up);
int down = ((this.Period - (i - lowestLowIndex)) / this.Period) * 100;
aroonSerie.Down.Add(down);
}
}
return aroonSerie;
}
}
Is there anyone else tried to do that before?
Here is the csv file I use:
https://drive.google.com/file/d/0Bwv_-8Q17wGaRDVCa2FhMWlyRUk/view
But the result sets for Aroon up and down don't match with the results of aroon function in TTR package for R.
table <- read.csv("table.csv", header = TRUE, sep = ",")
trend <- aroon(table[,c("High", "Low")], n=5)
View(trend)
Screenshot of R result:
Thanks in advance,
#anilca,
for full Disclosure, I learned alot of things to answer your question(i knew nothing in the Finetec...). Thank you! it was an interesting experience!
There are several problems in your implementation:
In the statements:
i - highestHighIndex
and
i - lowestLowIndex
the variable "i" is less or equal to highestHighIndex, lowestLowIndex
so statements:
this.Period - (i - highestHighIndex)
and
this.Period - (i - lowestLowIndex)
will returns the wrong values (most of the time...)
Aroon up and down both of them are percentage, therefore "int" is a wrong data structure.
Because all variables in:
(this.Period - (i - highestHighIndex)) / this.Period)
and
((this.Period - (i - lowestLowIndex)) / this.Period)
are integers you won't recieve the right value.
one more thing the numbers in your excel are sorted from the newest to the oldest.(it effects on the R package)
I've implemented the algorithm based on your code(and your data order...)
public class Aroon : IndicatorCalculatorBase
{
public override List<OhlcSample> OhlcList { get; set; }
private readonly int _period;
public int Period
{
get { return _period; }
}
public Aroon(int period)
{
_period = period;
}
public override IIndicatorSerie Calculate()
{
var aroonSerie = new AroonSerie();
for (var i = _period; i < OhlcList.Count; i++)
{
var aroonUp = CalculateAroonUp(i);
var aroonDown = CalculateAroonDown(i);
aroonSerie.Down.Add(aroonDown);
aroonSerie.Up.Add(aroonUp);
}
return aroonSerie;
}
private double CalculateAroonUp(int i)
{
var maxIndex = FindMax(i - _period, i);
var up = CalcAroon(i - maxIndex);
return up;
}
private double CalculateAroonDown(int i)
{
var minIndex = FindMin(i - _period, i);
var down = CalcAroon(i - minIndex);
return down;
}
private double CalcAroon(int numOfDays)
{
var result = ((_period - numOfDays)) * ((double)100 / _period);
return result;
}
private int FindMin(int startIndex, int endIndex)
{
var min = double.MaxValue;
var index = startIndex;
for (var i = startIndex; i <= endIndex; i++)
{
if (min < OhlcList[i].Low)
continue;
min = OhlcList[i].Low;
index = i;
}
return index;
}
private int FindMax(int startIndex, int endIndex)
{
var max = double.MinValue;
var index = startIndex;
for (var i = startIndex; i <= endIndex; i++)
{
if (max > OhlcList[i].High)
continue;
max = OhlcList[i].High;
index = i;
}
return index;
}
}
public abstract class IndicatorCalculatorBase
{
public abstract List<OhlcSample> OhlcList { get; set; }
public abstract IIndicatorSerie Calculate();
}
public interface IIndicatorSerie
{
List<double> Up { get; }
List<double> Down { get; }
}
internal class AroonSerie : IIndicatorSerie
{
public List<double> Up { get; private set; }
public List<double> Down { get; private set; }
public AroonSerie()
{
Up = new List<double>();
Down = new List<double>();
}
}
public class OhlcSample
{
public double High { get; private set; }
public double Low { get; private set; }
public OhlcSample(double high, double low)
{
High = high;
Low = low;
}
}
Use this test method for debugging:
private Aroon _target;
[TestInitialize]
public void TestInit()
{
_target=new Aroon(5)
{
OhlcList = new List<OhlcSample>
{
new OhlcSample(166.90, 163.65),
new OhlcSample(165.00, 163.12),
new OhlcSample(165.91, 163.21),
new OhlcSample(167.29, 165.11),
new OhlcSample(169.99, 166.84),
new OhlcSample(170.92, 167.90),
new OhlcSample(168.47, 165.90),
new OhlcSample(167.75, 165.75),
new OhlcSample(166.14, 161.89),
new OhlcSample(164.77, 161.44),
new OhlcSample(163.19, 161.49),
new OhlcSample(162.50, 160.95),
new OhlcSample(163.25, 158.84),
new OhlcSample(159.20, 157.00),
new OhlcSample(159.33, 156.14),
new OhlcSample(160.00, 157.00),
new OhlcSample(159.35, 158.07),
new OhlcSample(160.70, 158.55),
new OhlcSample(160.90, 157.66),
new OhlcSample(164.38, 158.45),
new OhlcSample(167.75, 165.70),
new OhlcSample(168.93, 165.60),
new OhlcSample(165.73, 164.00),
new OhlcSample(167.00, 164.66),
new OhlcSample(169.35, 165.01),
new OhlcSample(168.12, 164.65),
new OhlcSample(168.89, 165.79),
new OhlcSample(168.65, 165.57),
new OhlcSample(170.85, 166.00),
new OhlcSample(171.61, 169.10)
}
};
}
[TestMethod]
public void JustToHelpYou()
{
var result = _target.Calculate();
var expectedUp = new List<double>()
{
100,80,60,40,20,0,0,0, 0,0,40,20,0,100,100,100,100,80, 60,100,80,60,40,100,100
};
var expectedDown = new List<double>
{
20,0,0,100,100,80,100,100,100,100,80,60,40,20,0,0,40,20,0,0,40,20,0,40,20
};
Assert.IsTrue( result.Up.SequenceEqual(expectedUp));
Assert.IsTrue( result.Down.SequenceEqual(expectedDown));
}
Just Add implementation of method HighestBarNum and LowestBarnum from your code
public class Aroon
{
public bool AroonDown
{
get;
set;
}
public double Period
{
get;
set;
}
public Aroon()
{
}
public IList<double> Execute(IList<double> src)
{
if (!this.AroonDown)
{
return this.ExecuteUp(src);
}
return this.ExecuteDown(src);
}
public IList<double> ExecuteDown(IList<double> src)
{
double[] period = new double[src.Count];
for (int i = 1; i < src.Count; i++)
{
double num = LowestBarNum(src, i, Period);
period[i] = 100 * (Period - num) / Period;
}
return period;
}
public IList<double> ExecuteUp(IList<double> src)
{
double[] period = new double[src.Count];
for (int i = 1; i < src.Count; i++)
{
double num = HighestBarNum(src, i, Period);
period[i] = 100 * ((Period - num) / Period;
}
return period;
}}
class AroonData
{
public double AroonUp;
public double AroonDown;
}
Calculation Class:
class AroonCalculationData
{
public double PeriodHigh;
public double PeriodLow;
public double SetAroonUp(List<MarketData> period, double lastHigh)
{
/*reverse the set so we can look at it from the current tick
on back, and ticksSinceHigh will set correctly*/
period.Reverse();
int ticksSinceHigh = 0;
double high = 0.0;//Set 0 so anything will be higher
for (int i = 0; i < period.Count; i++)
{
if (period[i].high > high)
{
high = period[i].high;
ticksSinceHigh = i;
}
}
/*This bit if for if the high just ticked out
of List<MarketData>.
Including the current tick (i = 0), List<MarketData> period
only looks back (period - 1) days.
This Checks to see if the last high is still in the set. if it's
not, and is still the high for the period, then ticksSinceHigh
is set to (period)*/
PeriodHigh = high;
if (PeriodHigh < lastHigh)
{
ticksSinceHigh = period.Count;
}
/*Aroon-Up Formula*/
return (double)(period.Count - ticksSinceHigh ) / (double)period.Count * 100.0;
}
//ASIDE FROM LOOKING FOR LOWS INSTEAD OF HIGHS, SAME AS AROON-UP
public double SetAroonDown(List<MarketData> period, double lastLow)
{
period.Reverse();
int daysSinceLow = 0;
double low = double.MaxValue;//Set max so anything will be lower
for (int i = 0; i < period.Count; i++)
{
if (period[i].low < low)
{
low = period[i].low;
daysSinceLow = i;
}
}
PeriodLow = low;
if (PeriodLow > lastLow)
{
daysSinceLow = period.Count;
}
return (double)(period.Count - daysSinceLow) / (double)period.Count * 100.0;
}
}
Calling code:
public AroonData[] Aroon(List<MarketData> marketData, int period)
{
AroonCalculationData[] calculationData = new AroonCalculationData[marketData.Count]
AroonData[] aroon= new AroonData[marketData.Count]
for (int i = period; i < marketData.Count; i++)
{
/*GetRange(i - period + 1, period) add 1 so that the current tick is
included in look back.
For example, if (period = 10) the first loop (i = 10) then (i -
period + 1) = 1 the set will be marketData 1 - 10.*/
/*calculationData[i - 1].PeriodHigh and calculationData[i - 1].PeriodLow
are for looking back at the last tick's look back period high and
low*/
data[i].AroonUp = calculationData[i].SetAroonUp(marketData.GetRange(i - period + 1, period), calculationData[i - 1].PeriodHigh);
data[i].AroonDown = calculationData[i].SetAroonDown(marketData.GetRange(i - period + 1, period), calculationData[i - 1].PeriodLow);
}
}
Side note:
One problem I had was comparing my data to TD Ameritrades Aroon, until i figured out their period is really period-1, so if you're comparing to TD keep that in mind.
I am attempting to create a function that will create a set of cards
that can be randomly input into a list, but despite researching the solution
I can not figure out what I need to place in the parentheses when I called my
function, and when I return its variable.
using System;
using System.Collections.Generic;
using System.Text;
namespace BlackJackGameX
{
public class Deck
{
Random rNumber = new Random();
List<Card> Cards;
List<Card> ShuffledDeck;
public int iValue1 = 11;
public int iValue2 = 2;
public int iValue3 = 3;
public int iValue4 = 4;
public int iValue5 = 5;
public int iValue6 = 6;
public int iValue7 = 7;
public int iValue8 = 8;
public int iValue9 = 9;
public int iValue10 = 10;
public int iValue11 = 10;
public int iValue12 = 10;
public int iValue13 = 10;
I can not figure out what I need to put in the NewDeck parentheses.
public Deck()
{
Cards = NewDeck();
}
public void Shuffle()
{
for (int i = 0; i <= 51; ++i)
{
int c = rNumber.Next (1, 53);
ShuffledDeck.Add(Cards[c]);
}
}
private List<Card> NewDeck(Suit CardSuit, FaceValue CardValue, int iValue)
{
var AllSuits = new Suit[]
{
Suit.Spades,
Suit.Hearts,
Suit.Clubs,
Suit.Diamonds
};
var AllFaces = new FaceValue[]
{
FaceValue.Ace,
FaceValue.Two,
FaceValue.Three,
FaceValue.Four,
FaceValue.Five,
FaceValue.Six,
FaceValue.Seven,
FaceValue.Eight,
FaceValue.Nine,
FaceValue.Ten,
FaceValue.Jack,
FaceValue.Queen,
FaceValue.King
};
var AllValues = new int[]
{
iValue1,
iValue2,
iValue3,
iValue4,
iValue5,
iValue6,
iValue7,
iValue8,
iValue9,
iValue10,
iValue11,
iValue12,
iValue13
};
for (int i = 0; i <= 3; i++)
{
for (int j = 0; j <= 12; j++)
{
Card newCard = new Card(AllSuits[i], AllFaces[j], AllValues[j]);
}
}
I can not figure out what I need to put in the NewDeck parentheses
return NewDeck ();
}
public void Print()
{
Console.WriteLine(ShuffledDeck[1].CardValue);
Console.ReadLine();
}
}
}
As the signature of the method in question is:
private List<Card> NewDeck(Suit CardSuit, FaceValue CardValue, int iValue)
you will need to pass in values like the following:
return NewDeck(Suit.Spades, FaceValue.Ace, iValue1);
As Oren has said, inside the NewDeck method you do not use these values. Having the signature like this should also be OK:
private List<Card> NewDeck()