init
This commit is contained in:
65
MarketDataLib/Generator/Indicators/BandBreakIndicator.cs
Normal file
65
MarketDataLib/Generator/Indicators/BandBreakIndicator.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MarketData.Numerical;
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.DataAccess;
|
||||
using MarketData.Cache;
|
||||
using MarketData.Utils;
|
||||
|
||||
namespace MarketData.Generator.Indicators
|
||||
{
|
||||
// ***********************************************************************************
|
||||
public class BandBreakIndicator
|
||||
{
|
||||
private BandBreakIndicator()
|
||||
{
|
||||
}
|
||||
// This Indicator determines if a high price exceeds the K band (+2SSD) of the bollinger band over the past "dayCount" days.
|
||||
// If high price breaks the K band then we consider that to be a true indication.
|
||||
public static bool IsUpperBandBreakHigh(String symbol,DateTime pricingDate,int dayCount=20)
|
||||
{
|
||||
bool isBandBreak=false;
|
||||
int pricingDays=dayCount*4;
|
||||
if(pricingDays<60)pricingDays=60;
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,pricingDays);
|
||||
if(null==prices || 0==prices.Count)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*** IsUpperBandBreakHigh: Failed to retrieve prices for {0} on {1} for {2} days. ***",symbol,pricingDate.ToShortDateString(),pricingDays));
|
||||
return isBandBreak;
|
||||
}
|
||||
BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices);
|
||||
if(null==bollingerBands)return false;
|
||||
bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList());
|
||||
BollingerBandElement item=bollingerBands.Where(x => x.High > x.K).FirstOrDefault();
|
||||
if(null!=item)isBandBreak=true;
|
||||
return isBandBreak;
|
||||
}
|
||||
// This Indicator determines if a close price is equal to or less than the L band (-2SSD) of the bollinger band over the past "dayCount" days.
|
||||
// If close price breaks or is equal to the L band then we consider that to be a true indication.
|
||||
// If there is a violation then the date of the violation is return otherwise we return Epoch
|
||||
public static DateTime IsLowerBandBreakClose(String symbol,DateTime pricingDate,int dayCount=20)
|
||||
{
|
||||
DateTime bandBreakDate=Utility.Epoch;
|
||||
int pricingDays=dayCount*4;
|
||||
if(pricingDays<60)pricingDays=60;
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,pricingDays);
|
||||
if(null==prices || 0==prices.Count)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*** IsLowerBandBreakClose: Failed to retrieve prices for {0} on {1} for {2} days. ***",symbol,pricingDate.ToShortDateString(),pricingDays));
|
||||
return bandBreakDate;
|
||||
}
|
||||
BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices);
|
||||
if(null==bollingerBands || bollingerBands.Count<dayCount)return bandBreakDate;
|
||||
bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList());
|
||||
BollingerBandElement item=bollingerBands.Where(x => x.Close <= x.L).FirstOrDefault();
|
||||
if(null!=item)
|
||||
{
|
||||
bandBreakDate=item.Date;
|
||||
}
|
||||
return bandBreakDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Numerical;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// Richard Donchian Channel Breakout. Donchian used 20 days.
|
||||
|
||||
namespace MarketData.Generator.Indicators
|
||||
{
|
||||
public class ChannelBreakoutIndicator
|
||||
{
|
||||
private ChannelBreakoutIndicator()
|
||||
{
|
||||
}
|
||||
public static bool IsChannelBreakOut(DateTime tradeDate,Prices prices,int dayCount)
|
||||
{
|
||||
if(null==prices||prices.Count<dayCount||0==dayCount||prices[0].Date!=tradeDate) return false;
|
||||
return IsChannelBreakOut(prices[0],prices,dayCount);
|
||||
}
|
||||
public static bool IsChannelBreakOut(Price currentPrice,Prices prices,int dayCount)
|
||||
{
|
||||
if(null==prices||prices.Count<dayCount||null==currentPrice) return false;
|
||||
prices=new Prices(prices.Take(dayCount).ToList()); // use the dayCount range provided
|
||||
prices=new Prices(prices.Where(x => !(x.Date.Date.Equals(currentPrice.Date.Date))).ToList()); // make sure currentPrice is not in the list of prices
|
||||
int count=prices.Count(x => x.Close>=currentPrice.Close); // count how many closing prices are above or equal to our closing price
|
||||
return 0==count?true:false; // if no records then currentPrice is the max over the period so return true, otherwise return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
MarketDataLib/Generator/Indicators/MVPIndicator.cs
Normal file
62
MarketDataLib/Generator/Indicators/MVPIndicator.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MarketData.Numerical;
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.DataAccess;
|
||||
using MarketData.Cache;
|
||||
using MarketData.Utils;
|
||||
|
||||
namespace MarketData.Generator.Indicators
|
||||
{
|
||||
// ***********************************************************************************
|
||||
public class MVPIndicator
|
||||
{
|
||||
private static readonly double DAY_COUNT=15.00;
|
||||
private static readonly double MOMENTUM_MIN_DAYS=12.00;
|
||||
private MVPIndicator() // Marc Minervini "M"omentum, "V"olume, "P"rice
|
||||
{
|
||||
}
|
||||
public static bool IsTrue(String symbol,DateTime pricingDate)
|
||||
{
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,(int)DAY_COUNT+1);
|
||||
if(null==prices||DAY_COUNT+1>prices.Count) return false;
|
||||
double daysUp=0;
|
||||
double daysDown=0;
|
||||
bool qualifiesOnPrice=false;
|
||||
bool qualifiesOnVolume=false;
|
||||
bool qualifiesOnMomentum=false;
|
||||
|
||||
// Momentum Check
|
||||
for(int index=prices.Count-2;index>=0;index--)
|
||||
{
|
||||
Price currentPrice=prices[index];
|
||||
Price prevPrice=prices[index+1];
|
||||
if(currentPrice.Close>prevPrice.Close)daysUp++;
|
||||
else daysDown++;
|
||||
}
|
||||
if(0.00==daysDown) qualifiesOnMomentum=true;
|
||||
else qualifiesOnMomentum=daysUp>=MOMENTUM_MIN_DAYS?true:false;
|
||||
if(!qualifiesOnMomentum) return false;
|
||||
|
||||
// Volume Check
|
||||
double baseVolume=prices[prices.Count-1].Volume;
|
||||
for(int index=prices.Count-2;index>=0 && !qualifiesOnVolume;index--)
|
||||
{
|
||||
Price currentPrice=prices[index];
|
||||
double percentChangeInVolume=((double)currentPrice.Volume-baseVolume)/baseVolume;
|
||||
if(percentChangeInVolume>=.25)qualifiesOnVolume=true;
|
||||
}
|
||||
if(!qualifiesOnVolume)return false;
|
||||
|
||||
// Price check
|
||||
double cumulativeReturn=prices.GetCumulativeReturn();
|
||||
if(cumulativeReturn>=.20) qualifiesOnPrice=true;
|
||||
if(!qualifiesOnPrice) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
MarketDataLib/Generator/Indicators/NarrowRangeIndicator.cs
Normal file
47
MarketDataLib/Generator/Indicators/NarrowRangeIndicator.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using MarketData.MarketDataModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.Indicators
|
||||
{
|
||||
public class NarrowRangeIndicator
|
||||
{
|
||||
private NarrowRangeIndicator()
|
||||
{
|
||||
}
|
||||
// It is assumed that prices are in descending date order. (i.e.) The most recent price is in the lowest index position
|
||||
public static bool IsNarrowRangeEntry(DateTime date,Prices prices,int dayCount)
|
||||
{
|
||||
if(!IsInsideDay(date,prices))return false;
|
||||
if(!IsNarrowestRange(date,prices,dayCount))return false;
|
||||
return true;
|
||||
}
|
||||
private static bool IsInsideDay(DateTime date,Prices prices)
|
||||
{
|
||||
int index=prices.FindIndex(x=>x.Date.Date.Equals(date));
|
||||
if(-1==index||index+1>=prices.Count)return false;
|
||||
if(!(prices[index].High<=prices[index+1].High&&prices[index].Low>=prices[index+1].Low))return false;
|
||||
return true;
|
||||
}
|
||||
private static bool IsNarrowestRange(DateTime date,Prices prices,int dayCount)
|
||||
{
|
||||
int index=prices.FindIndex(x => x.Date.Date.Equals(date));
|
||||
double range=GetRange(prices,index);
|
||||
if(index+dayCount>=prices.Count-1)return false;
|
||||
for(int dayIndex=index+1;dayIndex<index+dayCount;dayIndex++)
|
||||
{
|
||||
double nextRange=GetRange(prices,dayIndex);
|
||||
if(nextRange<range)return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private static double GetRange(Prices prices,int index)
|
||||
{
|
||||
double range=prices[index].High-prices[index].Low;
|
||||
return Math.Abs(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
MarketDataLib/Generator/Indicators/OverExtendedIndicator.cs
Normal file
78
MarketDataLib/Generator/Indicators/OverExtendedIndicator.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MarketData.Numerical;
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.DataAccess;
|
||||
using MarketData.Cache;
|
||||
using MarketData.Utils;
|
||||
|
||||
namespace MarketData.Generator.Indicators
|
||||
{
|
||||
// ***********************************************************************************
|
||||
public class OverExtendedIndicator
|
||||
{
|
||||
private static double marginPercent=1.50; // The default margin is 1.00. 1.50 Gives the best results in backtests from 2013->2021
|
||||
private OverExtendedIndicator() // Also, regarding VioaltionThresshold below.... the best results were obtained with MarginePercent=1.5 and ViolationThresshol=1.00
|
||||
{
|
||||
}
|
||||
// UseOverExtendedIndicator:true/false
|
||||
// UseOverExtendedIndicatorDays:45
|
||||
// UseOverExtendedViolationThreshhold:2 breaks >=2 this number are considered to be violations
|
||||
// This Indicator determines if a price is overextended by looking at the K band of the bollinger band over the past "dayCount" days.
|
||||
// If closing price breaks the K band by more than 1.00% then we consider that to be an indication that the price is overextended.
|
||||
public static bool? IsOverextended(String symbol,DateTime pricingDate,int dayCount=20)
|
||||
{
|
||||
bool isOverExtended=false;
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4);
|
||||
if(null==prices || 0==prices.Count)return null;
|
||||
BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount);
|
||||
if(null==bollingerBands)return false;
|
||||
bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList());
|
||||
BollingerBandElement item=bollingerBands.Where(x => x.Close>x.K && (((x.Close-x.K)/x.K)*100.00)>marginPercent).FirstOrDefault();
|
||||
if(null!=item)isOverExtended=true;
|
||||
return isOverExtended;
|
||||
}
|
||||
// This method considers an overextended condition based upon an allowable number of upper band breaks
|
||||
public static bool? IsOverextended(String symbol,DateTime pricingDate,int dayCount=20,int violationThreshhold=1)
|
||||
{
|
||||
bool isOverExtended=false;
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4);
|
||||
if(null==prices||0==prices.Count) return null;
|
||||
BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount);
|
||||
if(null==bollingerBands) return false;
|
||||
bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList());
|
||||
List<BollingerBandElement> items=bollingerBands.Where(x => x.Close>x.K&&(((x.Close-x.K)/x.K)*100.00)>marginPercent).ToList();
|
||||
if(null==items)return null;
|
||||
if(items.Count>violationThreshhold)isOverExtended=true;
|
||||
return isOverExtended;
|
||||
}
|
||||
// This method considers an overextended condition based upon an allowable number of upper band breaks and user supplied marginPercent
|
||||
public static bool? IsOverextended(String symbol,DateTime pricingDate,int dayCount=20,int violationThreshhold=1,double paramMarginPercent=1.00)
|
||||
{
|
||||
bool isOverExtended=false;
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4);
|
||||
if(null==prices||0==prices.Count) return null;
|
||||
BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount);
|
||||
if(null==bollingerBands) return false;
|
||||
bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList());
|
||||
List<BollingerBandElement> items=bollingerBands.Where(x => x.Close>x.K&&(((x.Close-x.K)/x.K)*100.00)>paramMarginPercent).ToList();
|
||||
if(null==items) return null;
|
||||
if(items.Count>violationThreshhold) isOverExtended=true;
|
||||
return isOverExtended;
|
||||
}
|
||||
public static int? OverExtendedCount(String symbol,DateTime pricingDate,int dayCount=20)
|
||||
{
|
||||
Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4);
|
||||
if(null==prices||0==prices.Count) return null;
|
||||
BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount);
|
||||
if(null==bollingerBands) return null;
|
||||
bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList());
|
||||
List<BollingerBandElement> items=bollingerBands.Where(x => x.Close>x.K).ToList();
|
||||
if(null==items)return null;
|
||||
return items.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
MarketDataLib/Generator/Indicators/PriceTrendIndicator.cs
Normal file
44
MarketDataLib/Generator/Indicators/PriceTrendIndicator.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Numerical;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.Indicators
|
||||
{
|
||||
public class PriceTrendIndicatorResult
|
||||
{
|
||||
public PriceTrendIndicatorResult(bool isUptrend,double highPriceSlope=double.NaN,double lowPriceSlope=double.NaN)
|
||||
{
|
||||
this.IsUpTrend=isUptrend;
|
||||
this.HighPriceSlope=highPriceSlope;
|
||||
this.LowPriceSlope=lowPriceSlope;
|
||||
}
|
||||
public bool IsUpTrend{get;private set;}
|
||||
public double HighPriceSlope{get;private set;}
|
||||
public double LowPriceSlope{get; private set;}
|
||||
}
|
||||
public class PriceTrendIndicator
|
||||
{
|
||||
private PriceTrendIndicator()
|
||||
{
|
||||
}
|
||||
public static PriceTrendIndicatorResult IsUptrend(Prices prices,int dayCount)
|
||||
{
|
||||
if(null==prices||prices.Count<dayCount) return new PriceTrendIndicatorResult(false);
|
||||
float[] highPrices=prices.GetPricesHigh();
|
||||
highPrices=highPrices.Take(dayCount).ToArray();
|
||||
highPrices=Numerics.Reverse(ref highPrices);
|
||||
double highPricesSlope=Numerics.Slope(highPrices);
|
||||
if(highPricesSlope<0) return new PriceTrendIndicatorResult(false);
|
||||
float[] lowPrices=prices.GetPricesLow();
|
||||
lowPrices=lowPrices.Take(dayCount).ToArray();
|
||||
lowPrices=Numerics.Reverse(ref lowPrices);
|
||||
double lowPricesSlope=Numerics.Slope(lowPrices);
|
||||
if(lowPricesSlope<0) return new PriceTrendIndicatorResult(false);
|
||||
return new PriceTrendIndicatorResult(true,highPricesSlope,lowPricesSlope);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
MarketDataLib/Generator/Indicators/VolumeTrendIndicator.cs
Normal file
26
MarketDataLib/Generator/Indicators/VolumeTrendIndicator.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using MarketData.MarketDataModel;
|
||||
using MarketData.Numerical;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MarketData.Generator.Indicators
|
||||
{
|
||||
public class VolumeTrendIndicator
|
||||
{
|
||||
private VolumeTrendIndicator()
|
||||
{
|
||||
}
|
||||
public static bool IsUptrend(Prices prices,int dayCount)
|
||||
{
|
||||
if(null==prices||prices.Count<dayCount) return false;
|
||||
float[] volume=prices.GetVolume();
|
||||
volume=volume.Take(dayCount).ToArray();
|
||||
volume=Numerics.Reverse(ref volume);
|
||||
double volumeSlope=Numerics.Slope(volume);
|
||||
return volumeSlope>0.00?true:false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user