mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-25 13:58:04 +00:00
Add new data structures and event handling classes for trading platform. Include base classes, value and bar structs, event arguments, emitters, listeners. Update ruleset for SonarLint.
This commit is contained in:
@@ -1,44 +1,44 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
OVER - Generates +1 if A is above B, -1 if A is below B and 0 if A=B
|
||||
|
||||
Remarks:
|
||||
OVER.Cross generates 1 when A breaks B from below and -1 when A breaks B from above
|
||||
|
||||
</summary> */
|
||||
|
||||
public class CROSS_Series : Pair_TSeries_Indicator {
|
||||
public TSeries Cross { get; set; } = new();
|
||||
|
||||
private double _previous = double.NaN;
|
||||
public CROSS_Series(TSeries d1, TSeries d2) : base(d1, d2) {
|
||||
if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } }
|
||||
}
|
||||
public CROSS_Series(TSeries d1, double dd2) : base(d1, dd2) {
|
||||
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
|
||||
}
|
||||
public CROSS_Series(double dd1, TSeries d2) : base(dd1, d2) {
|
||||
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
|
||||
|
||||
double val = TValue1.v > TValue2.v ? 1 : -1;
|
||||
val = TValue1.v == TValue2.v ? 0 : val;
|
||||
double over = TValue1.v > TValue2.v ? 1 : val;
|
||||
|
||||
val = (_previous < over) ? 1 : -1;
|
||||
val = ((_previous == over) || Double.IsNaN(this._previous) || (this._previous == 0)) ? 0 : val;
|
||||
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t,val);
|
||||
|
||||
this._previous = over;
|
||||
|
||||
if (update) { base[^1] = result; }
|
||||
else { base.Add(result); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
OVER - Generates +1 if A is above B, -1 if A is below B and 0 if A=B
|
||||
|
||||
Remarks:
|
||||
OVER.Cross generates 1 when A breaks B from below and -1 when A breaks B from above
|
||||
|
||||
</summary> */
|
||||
|
||||
public class CROSS_Series : Pair_TSeries_Indicator {
|
||||
public TSeries Cross { get; set; } = new();
|
||||
|
||||
private double _previous = double.NaN;
|
||||
public CROSS_Series(TSeries d1, TSeries d2) : base(d1, d2) {
|
||||
if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } }
|
||||
}
|
||||
public CROSS_Series(TSeries d1, double dd2) : base(d1, dd2) {
|
||||
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
|
||||
}
|
||||
public CROSS_Series(double dd1, TSeries d2) : base(dd1, d2) {
|
||||
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
|
||||
|
||||
double val = TValue1.v > TValue2.v ? 1 : -1;
|
||||
val = TValue1.v == TValue2.v ? 0 : val;
|
||||
double over = TValue1.v > TValue2.v ? 1 : val;
|
||||
|
||||
val = (_previous < over) ? 1 : -1;
|
||||
val = ((_previous == over) || Double.IsNaN(this._previous) || (this._previous == 0)) ? 0 : val;
|
||||
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t,val);
|
||||
|
||||
this._previous = over;
|
||||
|
||||
if (update) { base[^1] = result; }
|
||||
else { base.Add(result); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,91 +1,91 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
EQUITY - Generates P&L portfolio based on trades signals and equity prices
|
||||
|
||||
</summary> */
|
||||
|
||||
|
||||
//base prices: bars.close
|
||||
//trade signals: trades
|
||||
//optional: long, short, long&short
|
||||
//optional: warmup period: warmup
|
||||
|
||||
/*
|
||||
|
||||
public class EQUITY_Series : Single_TSeries_Indicator {
|
||||
readonly TSeries inmarket; //for every bar
|
||||
private readonly TSeries _price;
|
||||
private double _equity;
|
||||
private readonly double _capital;
|
||||
|
||||
readonly int _warmup;
|
||||
double _cash;
|
||||
int _units;
|
||||
private bool _longbuy, _longsell;
|
||||
double _long_order, _open_order;
|
||||
double _investment_value;
|
||||
short _inmarket;
|
||||
|
||||
public EQUITY_Series(TSeries signal, TSeries price, int warmup = 0, double capital = 1000) : base(signal, period: 0, useNaN: false) {
|
||||
_capital = capital;
|
||||
_cash = _capital;
|
||||
_investment_value = 0;
|
||||
_warmup = (warmup > 0) ? warmup : 1;
|
||||
|
||||
inmarket = new();
|
||||
_longbuy = _longsell = false;
|
||||
_open_order = 0;
|
||||
_inmarket = 0;
|
||||
_units = 0;
|
||||
_long_order = 0;
|
||||
|
||||
_price = price; //we buy on the Open price of the NEXT bar
|
||||
_long_order = 0;
|
||||
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update) {
|
||||
|
||||
if (this.Count > _warmup) {
|
||||
|
||||
// harvest the gain-loss from previous day
|
||||
_investment_value = _units * _price[this.Count - 1].v;
|
||||
_equity = _cash + _investment_value;
|
||||
|
||||
|
||||
//execute orders from previous bar
|
||||
if (_longbuy && _inmarket == 0) { //time to execute the long buy
|
||||
_units = (int)(_cash / _price[this.Count - 1].v);
|
||||
_long_order = _units * _price[this.Count - 1].v;
|
||||
_cash -= _long_order;
|
||||
_open_order = _long_order;
|
||||
_equity = _cash + _open_order;
|
||||
_inmarket = 1;
|
||||
_longbuy = false;
|
||||
}
|
||||
|
||||
if (_longsell && _inmarket == 1) { //time to execute the long sell
|
||||
_long_order = (_units * _price[this.Count - 1].v);
|
||||
_cash += _long_order;
|
||||
_units = 0;
|
||||
|
||||
_open_order = 0;
|
||||
_equity = _cash + _open_order;
|
||||
_inmarket = 0;
|
||||
_longsell = false;
|
||||
}
|
||||
|
||||
if (_inmarket == 0 && TValue.v == 1) { _longbuy = true; } //out of market, enter long
|
||||
if (_inmarket == 1 && TValue.v == -1) { _longsell = true; } //long market, exit long
|
||||
|
||||
//Console.WriteLine($"{TValue.v,3}\t {(_inmarket)} : {_cash,10:f2} + {_units*_price[^1].v,7:f2} = {_equity-_capital:f2}");
|
||||
}
|
||||
inmarket.Add((TValue.t, (double)_inmarket));
|
||||
base.Add((TValue.t, _equity), update, _NaN);
|
||||
}
|
||||
}
|
||||
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
EQUITY - Generates P&L portfolio based on trades signals and equity prices
|
||||
|
||||
</summary> */
|
||||
|
||||
|
||||
//base prices: bars.close
|
||||
//trade signals: trades
|
||||
//optional: long, short, long&short
|
||||
//optional: warmup period: warmup
|
||||
|
||||
/*
|
||||
|
||||
public class EQUITY_Series : Single_TSeries_Indicator {
|
||||
readonly TSeries inmarket; //for every bar
|
||||
private readonly TSeries _price;
|
||||
private double _equity;
|
||||
private readonly double _capital;
|
||||
|
||||
readonly int _warmup;
|
||||
double _cash;
|
||||
int _units;
|
||||
private bool _longbuy, _longsell;
|
||||
double _long_order, _open_order;
|
||||
double _investment_value;
|
||||
short _inmarket;
|
||||
|
||||
public EQUITY_Series(TSeries signal, TSeries price, int warmup = 0, double capital = 1000) : base(signal, period: 0, useNaN: false) {
|
||||
_capital = capital;
|
||||
_cash = _capital;
|
||||
_investment_value = 0;
|
||||
_warmup = (warmup > 0) ? warmup : 1;
|
||||
|
||||
inmarket = new();
|
||||
_longbuy = _longsell = false;
|
||||
_open_order = 0;
|
||||
_inmarket = 0;
|
||||
_units = 0;
|
||||
_long_order = 0;
|
||||
|
||||
_price = price; //we buy on the Open price of the NEXT bar
|
||||
_long_order = 0;
|
||||
|
||||
if (base._data.Count > 0) { base.Add(base._data); }
|
||||
}
|
||||
|
||||
public override void Add((System.DateTime t, double v) TValue, bool update) {
|
||||
|
||||
if (this.Count > _warmup) {
|
||||
|
||||
// harvest the gain-loss from previous day
|
||||
_investment_value = _units * _price[this.Count - 1].v;
|
||||
_equity = _cash + _investment_value;
|
||||
|
||||
|
||||
//execute orders from previous bar
|
||||
if (_longbuy && _inmarket == 0) { //time to execute the long buy
|
||||
_units = (int)(_cash / _price[this.Count - 1].v);
|
||||
_long_order = _units * _price[this.Count - 1].v;
|
||||
_cash -= _long_order;
|
||||
_open_order = _long_order;
|
||||
_equity = _cash + _open_order;
|
||||
_inmarket = 1;
|
||||
_longbuy = false;
|
||||
}
|
||||
|
||||
if (_longsell && _inmarket == 1) { //time to execute the long sell
|
||||
_long_order = (_units * _price[this.Count - 1].v);
|
||||
_cash += _long_order;
|
||||
_units = 0;
|
||||
|
||||
_open_order = 0;
|
||||
_equity = _cash + _open_order;
|
||||
_inmarket = 0;
|
||||
_longsell = false;
|
||||
}
|
||||
|
||||
if (_inmarket == 0 && TValue.v == 1) { _longbuy = true; } //out of market, enter long
|
||||
if (_inmarket == 1 && TValue.v == -1) { _longsell = true; } //long market, exit long
|
||||
|
||||
//Console.WriteLine($"{TValue.v,3}\t {(_inmarket)} : {_cash,10:f2} + {_units*_price[^1].v,7:f2} = {_equity-_capital:f2}");
|
||||
}
|
||||
inmarket.Add((TValue.t, (double)_inmarket));
|
||||
base.Add((TValue.t, _equity), update, _NaN);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -1,34 +1,34 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
public enum OType {
|
||||
NIL = 0, // No position
|
||||
BTO = 1, // Buy to Open
|
||||
STC = 2, // Sell to Close
|
||||
STO = 3, // Sell to Open
|
||||
BTC = 4, // Buy to Close
|
||||
END = 5, // Exit the trade
|
||||
}
|
||||
|
||||
|
||||
public class TOrders : List<(DateTime t, OType o)> {
|
||||
|
||||
public void Add((DateTime t, OType o) TOrder, bool update = false)
|
||||
{
|
||||
if (update) { this[^1] = TOrder; }
|
||||
else { base.Add(TOrder); }
|
||||
OnEvent(update);
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnEvent(bool update = false) {
|
||||
Pub?.Invoke(this, new TSeriesEventArgs { update = update }); }
|
||||
public delegate void NewDataEventHandler(object source, TSeriesEventArgs args);
|
||||
public event NewDataEventHandler Pub;
|
||||
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
public enum OType {
|
||||
NIL = 0, // No position
|
||||
BTO = 1, // Buy to Open
|
||||
STC = 2, // Sell to Close
|
||||
STO = 3, // Sell to Open
|
||||
BTC = 4, // Buy to Close
|
||||
END = 5, // Exit the trade
|
||||
}
|
||||
|
||||
|
||||
public class TOrders : List<(DateTime t, OType o)> {
|
||||
|
||||
public void Add((DateTime t, OType o) TOrder, bool update = false)
|
||||
{
|
||||
if (update) { this[^1] = TOrder; }
|
||||
else { base.Add(TOrder); }
|
||||
OnEvent(update);
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnEvent(bool update = false) {
|
||||
Pub?.Invoke(this, new TSeriesEventArgs { update = update }); }
|
||||
public delegate void NewDataEventHandler(object source, TSeriesEventArgs args);
|
||||
public event NewDataEventHandler Pub;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user