karlwancl / Trady
Licence: apache-2.0
Trady is a handy library for computing technical indicators, and it targets to be an automated trading system that provides stock data feeding, indicator computing, strategy building and automatic trading. It is built based on .NET Standard 2.0.
Stars: ✭ 433
Projects that are alternatives of or similar to Trady
mooquant
MooQuant 是一个基于 pyalgotrade 衍生而来的支持 python3 的支持国内A股的量化交易框架。
Stars: ✭ 24 (-94.46%)
Mutual labels: stock, quant
TradingView-Machine-Learning-GUI
Let Python optimize the best stop loss and take profits for your TradingView strategy.
Stars: ✭ 396 (-8.55%)
Mutual labels: stock, strategy
Trading Signals
Technical indicators to run technical analysis with JavaScript / TypeScript. 📈
Stars: ✭ 118 (-72.75%)
Mutual labels: analysis, indicator
openctp
CTP开放平台提供A股、港股、美股、期货、期权等全品种接入通道,通过提供中泰证券XTP、华鑫证券奇点、东方证券OST、东方财富证券EMT、盈透证券TWS等各通道的CTPAPI接口,CTP程序可以无缝对接各股票柜台。平台也提供了一套基于TTS交易系统的模拟环境,同样提供了CTPAPI兼容接口,可以替代Simnow,为CTP量化交易开发者提供7x24可用的模拟环境。
Stars: ✭ 389 (-10.16%)
Mutual labels: stock, quant
MyTT
MyTT将通达信,同花顺,文华麦语言等指标公式,最简移植到Python中,核心库单个文件,仅百行代码,十几个核心函数,神奇的实现所有常见技术指标算法(不依赖talib库)的纯python实现和转换通达信MACD,RSI,BOLL,ATR,KDJ,CCI,PSY等公式,全部基于pandas函数计算方法封装,简洁且高性能,能非常方便的应用在股票指标公式,股市期货量化框架分析,自动程序化交易,数字货币量化等领域,它是您最精练的股市量化工具。Python library with most stock market indicators.
Stars: ✭ 888 (+105.08%)
Mutual labels: stock, quant
presso
Event-driven backtest/realtime quantitative trading system.
Stars: ✭ 59 (-86.37%)
Mutual labels: quant, strategy
Friartuck
Live Quant Trading Framework for Robinhood, using IEX Trading and AlphaVantage for Free Prices.
Stars: ✭ 142 (-67.21%)
Mutual labels: stock, quant
akshare
AKShare is an elegant and simple financial data interface library for Python, built for human beings! 开源财经数据接口库
Stars: ✭ 5,155 (+1090.53%)
Mutual labels: stock, quant
Awesome Ai In Finance
🔬 A curated list of awesome machine learning strategies & tools in financial market.
Stars: ✭ 910 (+110.16%)
Mutual labels: analysis, quant
Sphinx Quant
一个基于vnpy,支持多账户,多策略,实盘交易,数据分析,分布式在线回测,风险管理,多交易节点的量化交易系统;支持CTP期货,股票,期权,数字货币等金融产品
Stars: ✭ 217 (-49.88%)
Mutual labels: stock, quant
pystockfilter
Financial technical and fundamental analysis indicator library for pystockdb.
Stars: ✭ 26 (-94%)
Mutual labels: stock, quant
Trady
Trady is a handy library for computing technical indicators, and targets to be an automated trading system that provides stock data feeding, indicator computing, strategy building and automatic trading. It is built based on .NET Standard 2.0.
Read Before You Use
This library is a hobby project, and would probably making breaking changes, use with care when in production.
Currently Available Features
- Stock data feeding (including csv, yahoo finance, quandl, alphavantage, stooq)
- Indicator computing (including SMA, EMA, RSI, MACD, BB, etc.)
- Signal capturing by rules
- Strategy backtesting by buy/sell rule
v3.2.8 update
- Fixes IsBull, IsBear recognition, added IsDoji extension by @ridicoulous
- Added vwap indicator by @codebeaulieu
v3.2.7 update
- Added candles transformation by @ridicoulous
v3.2.2 update
- Fixes CommodityChannelIndex
v3.2 update
- Added WeightedMovingAverage, HullMovingAverage & KeltnerChannels
- Added AlphaVantage importer (thanks to @irperez)
- Reactivate support for QuandlImporter
- Boost performance on date time transformation (thanks to @pavlexander)
- Boost performance for various indicators (HistoricalHighest/HistoricalLowest/EmaOsc/Macd/ADLine/Obv/ParabolicSar, etc.)
- Update dependencies for importers
- Remove redundant sdCount parameter for Sd operation
- EffeciencyRatio & Kama now accepts nullable decimal as input
- Allow use of simple operation for ParabolicSar
- Renamed simple operation "PcDiff" to "RDiff"
For older version history, please refer to another markdown document here
Updates from 2.0.x to 3.0.0
Please refer to another markdown document here
Supported Platforms
- .NET Core 2.0 or above
- .NET Framework 4.6.1 or above
- Mono 5.4 or above
- Xamarin.iOS 10.4 or above
- Xamarin.Android 7.5 or above
- Xamarin.Mac 3.8 or above
Currently Supported Importers
- Csv file
- Yahoo Finance
- Quandl
- Stooq
- AlphaVantage
Currently Supported Indicators
Please refer to another markdown document here
How To Install
Nuget package is available in modules, please install the package according to the needs
// For importing
PM > Install-Package Trady.Importer
// For computing & backtesting
PM > Install-Package Trady.Analysis
How To Use
-
Tldr
-
Importing
-
Computing
-
Backtesting
-
Advanced
Tldr
var importer = new YahooFinanceImporter();
var candles = await importer.ImportAsync("FB");
var last = candles.Sma(30).Last();
Console.WriteLine($"{last.DateTime}, {last.Tick}");
Import stock data
// From Quandl wiki database
var importer = new QuandlWikiImporter(apiKey);
// From Yahoo Finance
var importer = new YahooFinanceImporter();
// From Stooq
var importer = new StooqImporter();
// From AlphaVantage
var importer = new AlphaVantageImporter(apiKey);
// From Google Finance (Temporarily not available now)
// var importer = new GoogleFinanceImporter();
// Or from dedicated csv file
var importer = new CsvImporter("FB.csv");
// Get stock data from the above importer
var candles = await importer.ImportAsync("FB");
Transform stock data to specified period before computation
// Transform the series for computation, downcast is forbidden
// Supported period: PerSecond, PerMinute, Per15Minutes, Per30Minutes, Hourly, BiHourly, Daily, Weekly, Monthly
var transformedCandles = candles.Transform<Daily, Weekly>();
Compute indicator
// This library supports computing from tuples or candles, extensions are recommended for computing
var closes = new List<decimal>{ ... };
var smaTs = closes.Sma(30);
var sma = closes.Sma(30)[index];
// or, traditional call
var sma = new SimpleMovingAverageByTuple(closes, 30)[index];
// the corresponding version of candle
var sma = new SimpleMovingAverage(candles, 30)[index];
Compute simple operation on an indicator
// Simple operation on indicator is supported, now supports only diff, rDiff, sma, sd
var closes = new List<decimal>{ ... };
var smaDiff = closes.Sma(30).Diff(index); // i-th term - (i-1)-th term
var smaSma = closes.Sma(30).Sma(10, index); // average(n items)
var smaRDiff = closes.Sma(30).RDiff(index); // (i-th term - (i-1)-th term) / (i-1)-th term * 100
var smaSd = closes.Sma(30).Sd(10, 2, index);
// This also applies to candles
Convert function to indicator
// Sometimes, we want to utilize the Analyzable infra for some simple indicators but doesn't want to implement a new class, we are adding AsAnalyzable for conversion from Func
// Before conversion, on the very top of your file, you should add
using AFunc = System.Func<System.Collections.Generic.IReadOnlyList<Trady.Core.Candle>, int, System.Collections.Generic.IReadOnlyList<decimal>, Trady.Core.Infrastructure.IAnalyzeContext<Trady.Core.Candle>, decimal?>;
// And use it in your code
AFunc aFunc = (c, i, p, ctx) => c[i].High - c[i].Low; // The four parameters: candles, index, parameters, context
var aFuncInstance = aFunc.AsAnalyzable(candles);
var a = aFuncInstance[index];
// You may also combine with simple operation computation
var aSma = aFuncInstance.Sma(30, index);
Register function for global use
// To use your func globally for analysis, you can register you func by using FuncRegistry.Register method
// The four parameters is the same as the above section, namely: candles, index, parameters, context
FuncRegistry.Register("modified_sma", (c, i, p, ctx) => ctx.Get<SimpleMovingAverage>(p[0])[i].Tick);
// You can use your func globally using the extension
var lastModifiedSmaValue = candles.Func("modified_sma", 10)[candles.Count() - 1];
// The library also support register by plain text expression, you can dynamically create an analyzable as follows:
// Please notice that you must follow the naming convention: c, i, p, ctx when using this approach
FuncRegistry.Register("dy_sma", "var sma = ctx.Get<SimpleMovingAverage>(10); return sma[i].Tick;");
// And the use case is similar:
var lastModifiedSmaValue = candles.Func("modified_sma")[candles.Count() - 1];
Capture signals by rules
// The following shows the number of candles that fulfill both the IsAboveSma(30) & IsAboveSma(10) rule
var rule = Rule.Create(c => c.IsAboveSma(30))
.And(c => c.IsAboveSma(10));
// Use context here for caching indicator results
using (var ctx = new AnalyzeContext(candles))
{
var validObjects = new SimpleRuleExecutor(ctx, rule).Execute();
Console.WriteLine(validObjects.Count());
}
Strategy building & backtesting
// Import your candles
var importer = new YahooFinanceImporter();
var fb = await importer.ImportAsync("FB");
var aapl = await importer.ImportAsync("AAPL");
// Build buy rule & sell rule based on various patterns
var buyRule = Rule.Create(c => c.IsFullStoBullishCross(14, 3, 3))
.And(c => c.IsMacdOscBullish(12, 26, 9))
.And(c => c.IsSmaOscBullish(10, 30))
.And(c => c.IsAccumDistBullish());
var sellRule = Rule.Create(c => c.IsFullStoBearishCross(14, 3, 3))
.Or(c => c.IsMacdBearishCross(12, 24, 9))
.Or(c => c.IsSmaBearishCross(10, 30));
// Create portfolio instance by using PortfolioBuilder
var runner = new Builder()
.Add(fb, 10)
.Add(aapl, 30)
.Buy(buyRule)
.Sell(sellRule)
.BuyWithAllAvailableCash()
.FlatExchangeFeeRate(0.001m)
.Premium(1)
.Build();
// Start backtesting with the portfolio
var result = await runner.RunAsync(10000);
// Get backtest result for the portfolio
Console.WriteLine(string.Format("Transaction count: {0:#.##}, P/L ratio: {1:0.##}%, Principal: {2:#}, Total: {3:#}",
resultresult.Transactions.Count(),
result.CorrectedProfitLoss * 100,
result.Principal,
result.CorrectedBalance));
Implement your own pattern through Extension
// Implement your pattern by creating a static class for extending IndexedCandle class
public static class IndexedCandleExtension
{
public static bool IsEma10Rising(this IndexedCandle ic)
=> ic.Get<ExponentialMovingAverage>(10).Diff(ic.Index).Tick.IsPositive();
public static bool IsEma10Dropping(this IndexedCandle ic)
=> ic.Get<ExponentialMovingAverage>(10).Diff(ic.Index).Tick.IsNegative();
public static bool IsEma10BullishCrossEma30(this IndexedCandle ic)
=> ic.Get<ExponentialMovingAverageOscillator>(10, 30).ComputeNeighbour(ic.Index).IsTrue(
(prev, current, next) => prev.Tick.IsNegative() && current.Tick.IsPositive());
public static bool IsEma10BearishCrossEma30(this IndexedCandle ic)
=> ic.Get<ExponentialMovingAverageOscillator>(10, 30).ComputeNeighbour(ic.Index).IsTrue(
(prev, current, next) => prev.Tick.IsPositive() && current.Tick.IsNegative());
}
// Use case
var buyRule = Rule.Create(c => c.IsEma10BullishCrossEma30()).And(c => c.IsEma10Rising());
var sellRule = Rule.Create(c => c.IsEma10BearishCrossEma30()).Or(c => c.IsEma10Dropping());
var runner = new Builder().Add(candles, 10).Buy(buyRule).Sell(sellRule).Build();
var result = await runner.RunAsync(10000, 1);
Register rule for global use
// To use your rule in global, you may register it by using RuleRegistry.Register method
RuleRegistry.Register("IsBelowSmaX", (ic, p) => ic.Get<SimpleMovingAverage>(p[0])[ic.Index].Tick.IsTrue(t => t > ic.Close));
// Or, using plain text
RuleRegistry.Register("IsBelowSma30", "ic.Get<SimpleMovingAverage>(30)[ic.Index].Tick.IsTrue(t => t > ic.Close)");
// Call it using GetRule method from AnalyzeContext
using (var ctx = new AnalyzeContext(candles))
{
var ruleX = ctx.GetRule("IsBelowSmaX", 30); // Substitute parameter to the rule
var rule30 = ctx.GetRule("IsBelowSma30");
var ruleXByRuleCreateEval = Rule.Create(ic => ic.Eval("IsBelowSmaX", 30)); // Create rule with indexedCandle Eval
var isAboveSma30Candles = new SimpleRuleExecutor(ctx, ruleX).Execute();
}
Implement your own importer
// You can also implement your own importer by implementing the IImporter interface
public class MyImporter : IImporter
{
public async Task<IReadOnlyList<IOhlcv>> ImportAsync(string symbol, DateTime? startTime = null, DateTime? endTime = null, PeriodOption period = PeriodOption.Daily, CancellationToken token = default(CancellationToken))
{
// Your implementation to return a list of candles
}
}
// Use case
var importer = new MyImporter();
var candles = await importer.ImportAsync("FB");
Implement your own indicator - Simple Type
// You can also implement your own indicator by extending the AnalyzableBase<TInput, TOutput> class
public class MyIndicator : AnalyzableBase<IOhlcv, AnalyzableTick<decimal?>>
{
// Backing indicator for the indicator
SimpleMovingAverageByTuple _sma;
public MyIndicator(IEnumerable<IOhlcv> inputs, int periodCount) : base(inputs)
{
// Initialize reference indicators, or other required stuff here
_sma = new SimpleMovingAverageByTuple(inputs.Select(i => i.Close).ToList(), periodCount);
}
// Implement the compute algorithm, uses mappedInputs, index & backing indicators for computation here
protected override AnalyzableTick<decimal?> ComputeByIndexImpl(IReadOnlyList<IOhlcv> mappedInputs, int index)
{
return new AnalyzableTick<decimal?>(mappedInputs[index].DateTime, _sma[index]);
}
}
// Use case
var results = new MyIndicator(candles, 30).Compute();
foreach (var r in results)
{
Console.WriteLine($"{r.DateTime}, {r.Tick.Value}");
}
Implement your own indicator - Cummulative Type
// You can implement your own indicator by extending the CummulativeAnalyzableBase<TInput, TOutput> class
public class MyCumulativeIndicator : CumulativeAnalyzableBase<IOhlcv, AnalyzableTick<decimal?>>
{
// Backing indicator for the indicator
readonly SimpleMovingAverageByTuple _sma;
public MyCumulativeIndicator(IEnumerable<IOhlcv> inputs, int periodCount) : base(inputs)
{
// Initialize reference indicators, or other required stuff here
_sma = new SimpleMovingAverageByTuple(inputs.Select(i => i.Close).ToList(), periodCount);
}
// Implement the compute algorithm for index > InitialValueIndex, uses mappedInputs, index, prev analyzable tick & backing indicators for computation here
protected override AnalyzableTick<decimal?> ComputeCumulativeValue(IReadOnlyList<IOhlcv> mappedInputs, int index, AnalyzableTick<decimal?> prevOutputToMap)
{
return new AnalyzableTick<decimal?>(mappedInputs[index].DateTime, _sma[index] + prevOutputToMap.Tick);
}
// Same for the above but for index = InitialValueIndex
protected override AnalyzableTick<decimal?> ComputeInitialValue(IReadOnlyList<IOhlcv> mappedInputs, int index)
{
return new AnalyzableTick<decimal?>(mappedInputs[index].DateTime, _sma[index]);
}
// You can also override the InitialValueIndex property & ComputeNullValue method if needed
}
// Use case
var results = new MyCumulativeIndicator(candles).Compute();
foreach (var r in results)
{
Console.WriteLine($"{r.DateTime}, {r.Tick.Value}");
}
Implement your own indicator - Moving-Average Type
// You can make use of the GenericMovingAverage class to get rid of implementing MA-related indicator on your own
public class MyGmaIndicator : AnalyzableBase<IOhlcv, AnalyzableTick<decimal?>>
{
GenericMovingAverage _gma;
public MyGmaIndicator(IEnumerable<IOhlcv> inputs, int periodCount) : base(inputs)
{
// parameters: initialValueIndex, initialValueFunction, indexValueFunction, smoothingFactorFunction
_gma = new GenericMovingAverage(
i => inputs.Select(ip => ip.Close).ElementAt(i),
2.0m / (periodCount + 1),
inputs.Count());
}
protected override AnalyzableTick<decimal?> ComputeByIndexImpl(IReadOnlyList<IOhlcv> mappedInputs, int index)
{
return new AnalyzableTick<decimal?>(mappedInputs[index].DateTime, _gma[index]);
}
}
Backlog
- (✔) Dynamically create indicator & rule patterns from text, allows internal call to dynamic generated stuffs
- () Complete other indicators (e.g. Keltner Channels, MA Envelopes, etc.)
- () Complete candlestick patterns
- (-) Add more rule patterns
- () Data-feeding: Add broker adaptor for real-time trade (e.g. interactive broker, etc.)
- () Graphing: Generate stock chart by indicator values
- () Pipelining: Provide simple programming interface for pipelining the real-time process, i.e. Data-feeding -> decision making by auto rule evaluation -> call to broker for trade -> auto adjust trading strategy based on prev decisions made -> (loop)
- () REPL for dynamic indicator creation, rule creation, strategy making, backtesting, etc.
- State saver & loader
- MORE, MORE AND MORE!!!!
Powered by
- CsvHelper (@JoshClose) : Great library for reading/ writing CSV file
Note that the project description data, including the texts, logos, images, and/or trademarks,
for each open source project belongs to its rightful owner.
If you wish to add or remove any projects, please contact us at [email protected].