Add ORB confluence factors (NR4/NR7, gap alignment, breakout volume, prior close) + session file logger
Some checks failed
Build and Test / build (push) Has been cancelled
Some checks failed
Build and Test / build (push) Has been cancelled
This commit is contained in:
299
tests/NT8.Core.Tests/Intelligence/OrbConfluenceFactorTests.cs
Normal file
299
tests/NT8.Core.Tests/Intelligence/OrbConfluenceFactorTests.cs
Normal file
@@ -0,0 +1,299 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NT8.Core.Common.Models;
|
||||
using NT8.Core.Intelligence;
|
||||
using NT8.Core.Logging;
|
||||
|
||||
namespace NT8.Core.Tests.Intelligence
|
||||
{
|
||||
[TestClass]
|
||||
public class OrbConfluenceFactorTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void NarrowRange_NR7_ScoresOne()
|
||||
{
|
||||
var calc = new NarrowRangeFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
intent.Metadata["daily_bars"] = CreateDailyContext(new double[] { 10, 10, 10, 10, 10, 10, 5 });
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(1.0, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NarrowRange_NR4_Scores075()
|
||||
{
|
||||
var calc = new NarrowRangeFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
intent.Metadata["daily_bars"] = CreateDailyContext(new double[] { 5, 5, 5, 10, 9, 8, 7 });
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(0.75, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NarrowRange_WideRange_ScoresLow()
|
||||
{
|
||||
var calc = new NarrowRangeFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
intent.Metadata["daily_bars"] = CreateDailyContext(new double[] { 5, 5, 5, 5, 5, 5, 12 });
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.IsTrue(result.Score <= 0.3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NarrowRange_MissingContext_DefaultsTo03()
|
||||
{
|
||||
var calc = new NarrowRangeFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(0.3, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NarrowRange_InsufficientBars_DefaultsTo03()
|
||||
{
|
||||
var calc = new NarrowRangeFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
intent.Metadata["daily_bars"] = CreateDailyContext(new double[] { 8, 7, 6, 5 });
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(0.3, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OrbRangeVsAtr_SmallRange_ScoresOne()
|
||||
{
|
||||
var calc = new OrbRangeVsAtrFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 10, 10, 10, 10, 10, 10, 10 });
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
intent.Metadata["orb_range_ticks"] = 8.0;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(1.0, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OrbRangeVsAtr_LargeRange_ScoresVeryLow()
|
||||
{
|
||||
var calc = new OrbRangeVsAtrFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 10, 10, 10, 10, 10, 10, 10 });
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
intent.Metadata["orb_range_ticks"] = 40.0;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.IsTrue(result.Score <= 0.15);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OrbRangeVsAtr_MissingContext_DefaultsTo05()
|
||||
{
|
||||
var calc = new OrbRangeVsAtrFactorCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(0.5, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GapDirection_LargeAlignedGap_ScoresOne()
|
||||
{
|
||||
var calc = new GapDirectionAlignmentCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
daily.Closes[daily.Count - 2] = 100.0;
|
||||
daily.TodayOpen = 106.0;
|
||||
daily.TradeDirection = 1;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(1.0, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GapDirection_LargeOpposingGap_ScoresVeryLow()
|
||||
{
|
||||
var calc = new GapDirectionAlignmentCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
daily.Closes[daily.Count - 2] = 100.0;
|
||||
daily.TodayOpen = 106.0;
|
||||
daily.TradeDirection = -1;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.IsTrue(result.Score <= 0.15);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GapDirection_FlatOpen_ScoresNeutral()
|
||||
{
|
||||
var calc = new GapDirectionAlignmentCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
daily.Closes[daily.Count - 2] = 100.0;
|
||||
daily.TodayOpen = 100.1;
|
||||
daily.TradeDirection = 1;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(0.55, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BreakoutVolume_ThreeX_ScoresOne()
|
||||
{
|
||||
var calc = new BreakoutVolumeStrengthCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
daily.BreakoutBarVolume = 3000.0;
|
||||
daily.AvgIntradayBarVolume = 1000.0;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(1.0, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BreakoutVolume_BelowAverage_ScoresLow()
|
||||
{
|
||||
var calc = new BreakoutVolumeStrengthCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
daily.BreakoutBarVolume = 800.0;
|
||||
daily.AvgIntradayBarVolume = 1200.0;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.IsTrue(result.Score <= 0.25);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PriorCloseStrength_LongTopQuartile_ScoresOne()
|
||||
{
|
||||
var calc = new PriorDayCloseStrengthCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
int prev = daily.Count - 2;
|
||||
daily.Lows[prev] = 100.0;
|
||||
daily.Highs[prev] = 120.0;
|
||||
daily.Closes[prev] = 118.0;
|
||||
daily.TradeDirection = 1;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(1.0, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PriorCloseStrength_LongBottomQuartile_ScoresLow()
|
||||
{
|
||||
var calc = new PriorDayCloseStrengthCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
int prev = daily.Count - 2;
|
||||
daily.Lows[prev] = 100.0;
|
||||
daily.Highs[prev] = 120.0;
|
||||
daily.Closes[prev] = 101.0;
|
||||
daily.TradeDirection = 1;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.IsTrue(result.Score <= 0.20);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PriorCloseStrength_ShortBottomQuartile_ScoresOne()
|
||||
{
|
||||
var calc = new PriorDayCloseStrengthCalculator(new BasicLogger("test"));
|
||||
var intent = CreateIntent();
|
||||
var daily = CreateDailyContext(new double[] { 8, 8, 8, 8, 8, 8, 8 });
|
||||
int prev = daily.Count - 2;
|
||||
daily.Lows[prev] = 100.0;
|
||||
daily.Highs[prev] = 120.0;
|
||||
daily.Closes[prev] = 101.0;
|
||||
daily.TradeDirection = -1;
|
||||
intent.Metadata["daily_bars"] = daily;
|
||||
|
||||
var result = calc.Calculate(intent, CreateContext(), CreateBar());
|
||||
|
||||
Assert.AreEqual(1.0, result.Score, 0.000001);
|
||||
}
|
||||
|
||||
private static StrategyIntent CreateIntent()
|
||||
{
|
||||
return new StrategyIntent(
|
||||
"ES",
|
||||
OrderSide.Buy,
|
||||
OrderType.Market,
|
||||
null,
|
||||
8,
|
||||
16,
|
||||
0.8,
|
||||
"test",
|
||||
new Dictionary<string, object>());
|
||||
}
|
||||
|
||||
private static StrategyContext CreateContext()
|
||||
{
|
||||
return new StrategyContext(
|
||||
"ES",
|
||||
DateTime.UtcNow,
|
||||
new Position("ES", 0, 0, 0, 0, DateTime.UtcNow),
|
||||
new AccountInfo(100000, 100000, 0, 0, DateTime.UtcNow),
|
||||
new MarketSession(DateTime.Today.AddHours(9.5), DateTime.Today.AddHours(16), true, "RTH"),
|
||||
new Dictionary<string, object>());
|
||||
}
|
||||
|
||||
private static BarData CreateBar()
|
||||
{
|
||||
return new BarData("ES", DateTime.UtcNow, 5000, 5005, 4998, 5002, 1000, TimeSpan.FromMinutes(5));
|
||||
}
|
||||
|
||||
private static DailyBarContext CreateDailyContext(double[] ranges)
|
||||
{
|
||||
DailyBarContext context = new DailyBarContext();
|
||||
context.Count = ranges.Length;
|
||||
context.Highs = new double[ranges.Length];
|
||||
context.Lows = new double[ranges.Length];
|
||||
context.Closes = new double[ranges.Length];
|
||||
context.Opens = new double[ranges.Length];
|
||||
context.Volumes = new long[ranges.Length];
|
||||
|
||||
for (int i = 0; i < ranges.Length; i++)
|
||||
{
|
||||
context.Lows[i] = 100.0;
|
||||
context.Highs[i] = 100.0 + ranges[i];
|
||||
context.Opens[i] = 100.0 + (ranges[i] * 0.25);
|
||||
context.Closes[i] = 100.0 + (ranges[i] * 0.75);
|
||||
context.Volumes[i] = 100000;
|
||||
}
|
||||
|
||||
context.TodayOpen = context.Closes[Math.Max(0, context.Count - 2)] + 1.0;
|
||||
context.BreakoutBarVolume = 1000.0;
|
||||
context.AvgIntradayBarVolume = 1000.0;
|
||||
context.TradeDirection = 1;
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user