private string Formula_EMA(SchemaInstrument formula, LocalFormula localFormula, List <int> selectedIndex, List <RecordInstrument> values) { var retval = string.Empty; var closing = GetDouble(selectedIndex.Count - 1, localFormula, selectedIndex, values); var previous = GetValueInstrument(selectedIndex.Count - 2, selectedIndex, values); var previousEma = Double.Parse(previous.Values[localFormula.Items[0].FieldName]); if (previousEma == 0) { var sum = 0d; for (var i = 1; i < selectedIndex.Count; i++) { sum += GetDouble(i, localFormula, selectedIndex, values); } var avg = (sum / (selectedIndex.Count - 1)); retval = (avg == 0 ? null : avg.ToString()); } else { var multiplier = (2d / (selectedIndex.Count + 1)); var ema = closing * multiplier + previousEma * (1 - multiplier); retval = (ema == 0 ? null : ema.ToString()); } return(retval); }
public void TransformData(SchemaInstrument formula, List <SchemaInstrument> instruments, List <RecordInstrument> values) { //if (!string.IsNullOrEmpty(formula.Transform)) //{ var localFormula = GetUnit(formula); var selected = GetSelected(values, localFormula); if (selected.Count > 0) { var value = values[selected[0]].Values[formula.Key]; foreach (var transform in localFormula.Transform) { switch (transform.Key.ToLower()) { case "normalise": if (!string.IsNullOrEmpty(value)) { value = String.Format("{0:0.000000}", Math.Round((Convert.ToDouble(value) - Convert.ToDouble(transform.Value[0])) / (Convert.ToDouble(transform.Value[1]) - Convert.ToDouble(transform.Value[0])), 6)); } break; case "categorise": var categories = new Dictionary <string, string>(); for (var i = 1; i < transform.Value.Count; i++) { var splt = transform.Value[i].Split('='); categories.Add(splt[0], splt[1]); } if (categories.ContainsKey(value)) { value = categories[value]; } break; default: break; } var transformKey = $"{formula.Key}_t"; values[selected[0]].Values[transformKey] = value; } } //} }
public WatchFile(string watchFileUri, JObject parseObject) { try { WatchFileUri = watchFileUri; Schemas = new List <Schema>(); Alias = new Dictionary <string, string>(); MergeFieldList = new List <string>(); MergeCaptureList = new List <string>(); DistinctFieldList = new List <string>(); DistinctCaptureList = new List <string>(); ChartFieldList = new List <string>(); ChartCaptureList = new List <string>(); WatchFileId = parseObject["watchfileid"].ToString(); WatchName = parseObject["watchname"].ToString(); Currency = parseObject["currency"].ToString().ToUpper(); var assembly = Assembly.GetExecutingAssembly(); if (parseObject.ContainsKey("alias")) { foreach (JObject alias in parseObject["alias"]) { if (!IsValid(alias, "alias") || !IsValid(alias, "name")) { throw new Exception("Alias or Name missing from watch file settings"); } Alias.Add(alias["alias"].ToString(), alias["name"].ToString()); } } foreach (var alias in Alias.ToArray()) { Alias[alias.Key] = Substitute(alias.Value); } foreach (JObject schema in parseObject["schemas"]) { Type codeType; var watchSchema = new Schema(); if (!schema.ContainsKey("codelibrary")) { codeType = typeof(DefaultCodeLibrary); } else { codeType = assembly.GetType(schema["codelibrary"].ToString()); } watchSchema.SchemaId = Substitute(schema["schemaid"].ToString()); watchSchema.SchemaName = Substitute(schema["schemaname"].ToString()); watchSchema.Unit = (SchemaInstrument.enmUnit)Enum.Parse(typeof(SchemaInstrument.enmUnit), schema["unit"].ToString()); watchSchema.UnitValue = double.Parse(schema["unitvalue"].ToString()); watchSchema.IsActive = (schema.ContainsKey("isactive") ? bool.Parse(schema["isactive"].ToString()) : false); watchSchema.SchemaInstruments = new List <SchemaInstrument>(); watchSchema.CodeLibrary = (ICodeLibrary)Activator.CreateInstance(codeType); M(enmMessageType.Debug, String.Format("WatchList.cstor: CodeLibrary [{0}] loaded for {1}", codeType, watchSchema.SchemaId)); watchSchema.Settings = new Dictionary <string, string>(); if (schema.ContainsKey("settings")) { foreach (JObject setting in schema["settings"]) { if (!IsValid(setting, "key") || !IsValid(setting, "value")) { throw new Exception("Key or Value missing from watch file settings"); } watchSchema.Settings.Add(setting["key"].ToString(), Substitute(setting["value"].ToString())); } } // TODO NEED TO VALIDATE SCHEMA --> // TODO NO RANGES with MINUS FIGURE ALLOWED // TODO Should only be one ISPREDICT = TRUE setting // TODO There must be at least one predict key // TODO Alias must be 3 characters or more // TODO Some methods do not allow minus values, see attributes // TODO Some methods do not allow ranges, see attributes // TODO If a field in the "value" element refers to a field that has not been collected then it is in the wrong order to capture or calculate // TODO Check two instruments are not writing to same field // TODO Key is not allowed with _ at the end, this is used to indicate a transformed field // TODO Predict key must be the first column, now called isnewrecord // TODO All formula items must reference rows <=0 i.e. minus figures or zero // TODO Range values must be 2 items or more foreach (JObject instrument in schema["instruments"]) { var isActive = (instrument.ContainsKey("isactive") ? bool.Parse(instrument["isactive"].ToString()) : true); if (isActive) { var schemaInstrument = new SchemaInstrument(); schemaInstrument.IsNewRecordEvent = (instrument.ContainsKey("isnewrecord") ? bool.Parse(instrument["isnewrecord"].ToString()) : false); schemaInstrument.IsColumn = (instrument.ContainsKey("iscolumn") ? bool.Parse(instrument["iscolumn"].ToString()) : true); schemaInstrument.IsSignal = (instrument.ContainsKey("issignal") ? bool.Parse(instrument["issignal"].ToString()) : false); schemaInstrument.CacheKey = $"{watchSchema.SchemaId}_{instrument["key"]}"; schemaInstrument.Key = instrument["key"].ToString(); schemaInstrument.Value = Substitute(instrument["value"].ToString()); schemaInstrument.Name = Substitute(instrument["name"].ToString()); schemaInstrument.Transform = (instrument.ContainsKey("transform") ? Substitute(instrument["transform"].ToString()) : null); schemaInstrument.Type = (instrument.ContainsKey("type") ? (SchemaInstrument.enmType)Enum.Parse(typeof(SchemaInstrument.enmType), instrument["type"].ToString()) : enmType.formula); schemaInstrument.DataType = (instrument.ContainsKey("datatype") ? (SchemaInstrument.enmDataType)Enum.Parse(typeof(SchemaInstrument.enmDataType), instrument["datatype"].ToString()) : enmDataType.@double); //schemaInstrument.Unit = (schemaInstrument.Type == enmType.capture ? enmUnit.none : unit); // (instrument.ContainsKey("unit") ? (SchemaInstrument.enmUnit)Enum.Parse(typeof(SchemaInstrument.enmUnit), instrument["unit"].ToString()) : (schemaInstrument.Type == enmType.capture ? enmUnit.none : SchemaInstrument.enmUnit.ticks)); //schemaInstrument.UnitValue = (schemaInstrument.Type == enmType.capture ? 0 : unitValue); var isFuture = false; if (schemaInstrument.Type == enmType.formula) { var splt = schemaInstrument.Value.Split(";")[0].Split(","); isFuture = (Convert.ToDouble(splt[1]) < 0); } schemaInstrument.IsFuture = isFuture; schemaInstrument.Settings = new Dictionary <string, string>(); if (instrument.ContainsKey("settings")) { foreach (JObject setting in instrument["settings"]) { schemaInstrument.Settings.Add(setting["key"].ToString(), Substitute(setting["value"].ToString())); } } if (schemaInstrument.Type == SchemaInstrument.enmType.capture) { if (schemaInstrument.Name.EndsWith("TICK")) { if (!DistinctCaptureList.Exists(x => x.Equals(schemaInstrument.Name))) { DistinctCaptureList.Add(schemaInstrument.Name); } if (!DistinctFieldList.Exists(x => x.Equals(schemaInstrument.Value))) { DistinctFieldList.Add(schemaInstrument.Value); } } else if (schemaInstrument.Name.StartsWith("CHART")) { if (!ChartCaptureList.Exists(x => x.Equals(schemaInstrument.Name))) { ChartCaptureList.Add(schemaInstrument.Name); } if (!ChartFieldList.Exists(x => x.Equals(schemaInstrument.Value))) { ChartFieldList.Add(schemaInstrument.Value); } } else { if (!MergeCaptureList.Exists(x => x.Equals(schemaInstrument.Name))) { MergeCaptureList.Add(schemaInstrument.Name); } if (!MergeFieldList.Exists(x => x.Equals(schemaInstrument.Value))) { MergeFieldList.Add(schemaInstrument.Value); } } } if (!string.IsNullOrEmpty(schemaInstrument.Transform)) { var transform = schemaInstrument.Transform.Split(','); var foundDataType = Enum.IsDefined(typeof(enmDataType), transform[transform.Length - 1]); var dataType = (foundDataType ? (enmDataType)Enum.Parse(typeof(enmDataType), transform[transform.Length - 1]) : schemaInstrument.DataType); SchemaInstrument transformInstrument = new SchemaInstrument() { IsColumn = schemaInstrument.IsColumn, DataType = dataType, Key = $"{schemaInstrument.Key}_t", IsSignal = schemaInstrument.IsSignal, Settings = schemaInstrument.Settings, Type = SchemaInstrument.enmType.transform }; schemaInstrument.IsSignal = false; schemaInstrument.IsColumn = false; schemaInstrument.Transform = (foundDataType ? string.Join(',', transform, 0, transform.Length - 1) : schemaInstrument.Transform); watchSchema.SchemaInstruments.Add(transformInstrument); } watchSchema.SchemaInstruments.Add(schemaInstrument); } } SchemaInstrument completedInstrument = new SchemaInstrument() { IsColumn = false, DataType = enmDataType.@string, Key = "completed", IsSignal = false, Settings = new Dictionary <string, string>(), Type = SchemaInstrument.enmType.transform, Value = new String('X', watchSchema.SchemaInstruments.Where(x => (x.Type == enmType.transform || x.Type == enmType.capture || x.Type == enmType.formula) && !x.IsFuture).Count()) }; watchSchema.SchemaInstruments.Add(completedInstrument); watchSchema.CodeLibrary.Initialise(watchSchema); Schemas.Add(watchSchema); } Loaded = DateTime.Now; CheckSum = GetCheckSum(parseObject.ToString()); MergeFieldList.Sort(); MergeCaptureList.Sort(); } catch (Exception ex) { M(enmMessageType.Error, $"WatchList.cstor ERROR: Please check your watch file format [{ex.Message}]"); throw ex; } }
public void ExecuteMethod(SchemaInstrument formula, List <RecordInstrument> values) { var localFormula = GetUnit(formula); var selectedIndex = GetSelected(values, localFormula); var isCapture = (selectedIndex.Count >= 1); var isValid = CheckValid(values, selectedIndex, localFormula); if (isCapture && isValid) { var target = values[selectedIndex[0]]; string newValue = "0"; bool allowNull = true; switch (System.Enum.Parse(typeof(enmProcess), formula.Name.ToLower())) { case enmProcess.signal: if (selectedIndex.Count == 3) { var change = (GetDouble(1, localFormula, selectedIndex, values) - GetDouble(2, localFormula, selectedIndex, values)); var signalRange = (formula.Settings.ContainsKey("range") ? double.Parse(formula.Settings["range"]) : 5); newValue = (change > signalRange ? $"1": (change < -signalRange ? $"-1" : "0")); allowNull = false; } break; case enmProcess.getvalue: if (selectedIndex.Count == 2) { newValue = GetString(1, localFormula, selectedIndex, values); } break; case enmProcess.count: if (selectedIndex.Count >= 1) { var count = 0; for (var i = 1; i <= (selectedIndex.Count - 1); ++i) { count++; } newValue = count.ToString(); } break; case enmProcess.changedvalue: if (selectedIndex.Count == 3) { newValue = (GetDouble(1, localFormula, selectedIndex, values) - GetDouble(2, localFormula, selectedIndex, values)).ToString(); } break; case enmProcess.percentage: if (selectedIndex.Count == 3) { var v1 = GetDouble(1, localFormula, selectedIndex, values); var v2 = GetDouble(2, localFormula, selectedIndex, values); var difference = (v1 - v2); var percentage = difference / ((v1 + v2) / 2) * 100; newValue = String.Format("{0:0.000}", percentage); } break; case enmProcess.roc: if (selectedIndex.Count == 3) { var v1 = GetDouble(1, localFormula, selectedIndex, values); var v2 = GetDouble(2, localFormula, selectedIndex, values); var roc = ((v1 / v2) - 1) * 100; newValue = String.Format("{0:0.000}", roc); } break; case enmProcess.changedinterval: if (selectedIndex.Count == 3) { newValue = (GetValueInstrument(1, selectedIndex, values).Time - GetValueInstrument(2, selectedIndex, values).Time).ToString(); } break; case enmProcess.average: if (selectedIndex.Count >= 3) { var sum = 0d; for (var i = 1; i < selectedIndex.Count; i++) { sum += GetDouble(i, localFormula, selectedIndex, values); } var average = (sum / (selectedIndex.Count - 1)); newValue = String.Format("{0:0.00}", average); } break; case enmProcess.ema: if (selectedIndex.Count >= 3) { newValue = String.Format("{0:0.00}", Formula_EMA(formula, localFormula, selectedIndex, values)); } break; case enmProcess.macd: if (selectedIndex.Count == 3) { var v1 = GetDouble(1, localFormula, selectedIndex, values); var v2 = GetDouble(2, localFormula, selectedIndex, values); newValue = (Convert.ToDouble(v1) - Convert.ToDouble(v2)).ToString(); } break; case enmProcess.rsi: if (selectedIndex.Count >= 3) { var gain = 0d; var loss = 0d; var times = string.Empty; for (var i = 2; i < selectedIndex.Count; i++) { var v1 = GetDouble(i, localFormula, selectedIndex, values); var v2 = GetDouble(i - 1, localFormula, selectedIndex, values); var diff = v2 - v1; if (diff <= 0) { loss += Math.Abs(diff); } else { gain += diff; } times += "X"; } var rsi = (100 - (100 / (1 + (gain / (selectedIndex.Count - 2)) / (loss / (selectedIndex.Count - 2))))); newValue = String.Format("{0:0.00}", rsi); } break; case enmProcess.standarddeviation: if (selectedIndex.Count >= 3) { var sum = 0d; for (var i = 1; i < selectedIndex.Count; i++) { sum += GetDouble(i, localFormula, selectedIndex, values); } var average = (sum / (selectedIndex.Count - 1)); sum = 0d; for (var i = 1; i < selectedIndex.Count; i++) { var val = GetDouble(i, localFormula, selectedIndex, values) - average; sum += (val * val); } average = (sum / (selectedIndex.Count - 1)); var stdDev = (average * average); newValue = String.Format("{0:0.00}", average); } break; case enmProcess.stochasticoscillator: if (selectedIndex.Count >= 3) { var max = 0d; var min = Double.MaxValue; for (var i = 1; i < selectedIndex.Count; i++) { var val = GetDouble(i, localFormula, selectedIndex, values); max = Math.Max(val, max); min = Math.Min(val, min); } var latest = GetDouble(selectedIndex.Count - 1, localFormula, selectedIndex, values); var stoch = ((latest - min) / (max - min)); newValue = String.Format("{0:0.00}", stoch); } break; default: break; } newValue = (newValue == "0" && allowNull ? null : newValue); target.Values[localFormula.Items[0].FieldName] = newValue; } }
private LocalFormula GetUnit(SchemaInstrument formula) { var retval = new LocalFormula(); if (CachedFormula.ContainsKey(formula.CacheKey)) { retval = CachedFormula[formula.CacheKey]; } else { retval.Key = formula.Key; retval.Items = new List <LocalFormula.ItemInfo>(); retval.Value = formula.Value; retval.Unit = formula.Unit; retval.Type = formula.Type; retval.DataType = formula.DataType; int min = int.MaxValue; int max = int.MinValue; if (formula.Transform != null) { var transforms = formula.Transform.Split(';'); for (var i = 0; i < transforms.Length; i++) { retval.Transform = new Dictionary <string, List <string> >(); var items = transforms[i].Split(','); var args = new string[items.Length - 1]; Array.Copy(items, 1, args, 0, args.Length); retval.Transform.Add(items[0], args.ToList <string>()); } } var fields = retval.Value.Split(';'); if (formula.Type == enmType.formula) { for (var i = 0; i < fields.Length; i++) { var item = fields[i].Split(','); if (item.Length == 2) { var fieldName = item[0]; var selectedRows = item[1]; retval.ValueType = (selectedRows.Contains('>') ? enmValueType.range : (selectedRows.Contains('~') ? enmValueType.scale : enmValueType.single)); if (retval.ValueType == enmValueType.single) { var y = int.Parse(selectedRows); min = Math.Min(min, y); max = Math.Max(max, y); retval.Items.Add(new LocalFormula.ItemInfo(fieldName, y)); } else if (retval.ValueType == enmValueType.range) // && retval.Unit == enmUnit.ticks) { var range = selectedRows.Split(">"); var a = int.Parse(range[0]); var b = int.Parse(range[1]); if (a > b) { (a, b) = (b, a); } for (var x = a; x <= b; x++) { min = Math.Min(min, x); max = Math.Max(max, x); retval.Items.Add(new LocalFormula.ItemInfo(fieldName, x)); } } //else if (retval.ValueType == enmValueType.range && retval.Unit == enmUnit.seconds) //{ // var range = selectedRows.Split(">"); // var a = int.Parse(range[0]); // var b = int.Parse(range[1]); // retval.Items.Add(new LocalFormula.ItemInfo(fieldName, a)); // retval.Items.Add(new LocalFormula.ItemInfo(fieldName, b)); //} else { var range = selectedRows.Split("~"); foreach (var x in range) { var y = int.Parse(x); min = Math.Min(min, y); max = Math.Max(max, y); retval.Items.Add(new LocalFormula.ItemInfo(fieldName, y)); } } } else { throw new Exception("Formula item in value element must have <field>,<position> combination"); } } retval.Range = max - min + 1; retval.Min = min; retval.Max = max; } CachedFormula.Add(formula.CacheKey, retval); } return(retval); }