chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:02:50 +08:00
commit 0fc60fdcb1
5008 changed files with 910633 additions and 0 deletions
@@ -0,0 +1,127 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using Python.Runtime;
using QuantConnect.Interfaces;
using System.Collections.Generic;
using QuantConnect.Util;
namespace QuantConnect.Algorithm.Framework.Alphas.Analysis
{
/// <summary>
/// Encapsulates the storage of insights.
/// </summary>
public class InsightManager : InsightCollection
{
private readonly IAlgorithm _algorithm;
private IInsightScoreFunction _insightScoreFunction;
/// <summary>
/// Creates a new instance
/// </summary>
/// <param name="algorithm">The associated algorithm instance</param>
public InsightManager(IAlgorithm algorithm)
{
_algorithm = algorithm;
}
/// <summary>
/// Process a new time step handling insights scoring
/// </summary>
/// <param name="utcNow">The current utc time</param>
public void Step(DateTime utcNow)
{
_insightScoreFunction?.Score(this, utcNow);
}
/// <summary>
/// Sets the insight score function to use
/// </summary>
/// <param name="insightScoreFunction">Model that scores insights</param>
public void SetInsightScoreFunction(IInsightScoreFunction insightScoreFunction)
{
_insightScoreFunction = insightScoreFunction;
}
/// <summary>
/// Sets the insight score function to use
/// </summary>
/// <param name="insightScoreFunction">Model that scores insights</param>
public void SetInsightScoreFunction(PyObject insightScoreFunction)
{
_insightScoreFunction = PythonUtil.CreateInstanceOrWrapper<IInsightScoreFunction>(
insightScoreFunction,
py => new InsightScoreFunctionPythonWrapper(py)
);
}
/// <summary>
/// Expire the insights of the given symbols
/// </summary>
/// <param name="symbols">Symbol we want to expire insights for</param>
public void Expire(IEnumerable<Symbol> symbols)
{
if (symbols == null)
{
return;
}
foreach (var symbol in symbols)
{
if (TryGetValue(symbol, out var insights))
{
Expire(insights);
}
}
}
/// <summary>
/// Cancel the insights of the given symbols
/// </summary>
/// <param name="symbols">Symbol we want to cancel insights for</param>
public void Cancel(IEnumerable<Symbol> symbols)
{
Expire(symbols);
}
/// <summary>
/// Expire the given insights
/// </summary>
/// <param name="insights">Insights to expire</param>
public void Expire(IEnumerable<Insight> insights)
{
if (insights == null)
{
return;
}
var currentUtcTime = _algorithm.UtcTime;
foreach (var insight in insights)
{
insight.Expire(currentUtcTime);
}
}
/// <summary>
/// Cancel the given insights
/// </summary>
/// <param name="insights">Insights to cancel</param>
public void Cancel(IEnumerable<Insight> insights)
{
Expire(insights);
}
}
}
@@ -0,0 +1,47 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Defines a collection of insights that were generated at the same time step
/// </summary>
public class GeneratedInsightsCollection
{
/// <summary>
/// The utc date time the insights were generated
/// </summary>
public DateTime DateTimeUtc { get; }
/// <summary>
/// The generated insights
/// </summary>
public Insight[] Insights { get; }
/// <summary>
/// Initializes a new instance of the <see cref="GeneratedInsightsCollection"/> class
/// </summary>
/// <param name="dateTimeUtc">The utc date time the sinals were generated</param>
/// <param name="insights">The generated insights</param>
public GeneratedInsightsCollection(DateTime dateTimeUtc, Insight[] insights)
{
DateTimeUtc = dateTimeUtc;
Insights = insights;
}
}
}
@@ -0,0 +1,31 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Algorithm.Framework.Alphas.Analysis;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Abstraction in charge of scoring insights
/// </summary>
public interface IInsightScoreFunction
{
/// <summary>
/// Method to evaluate and score insights for each time step
/// </summary>
void Score(InsightManager insightManager, DateTime utcTime);
}
}
@@ -0,0 +1,747 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using QuantConnect.Algorithm.Framework.Alphas.Serialization;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Defines a alpha prediction for a single symbol generated by the algorithm
/// </summary>
/// <remarks>
/// Serialization of this type is delegated to the <see cref="InsightJsonConverter"/> which uses the <see cref="SerializedInsight"/> as a model.
/// </remarks>
[JsonConverter(typeof(InsightJsonConverter))]
public class Insight
{
private readonly IPeriodSpecification _periodSpecification;
/// <summary>
/// Gets the unique identifier for this insight
/// </summary>
public Guid Id { get; protected set; }
/// <summary>
/// Gets the group id this insight belongs to, null if not in a group
/// </summary>
public Guid? GroupId { get; protected set; }
/// <summary>
/// Gets an identifier for the source model that generated this insight.
/// </summary>
public string SourceModel { get; set; }
/// <summary>
/// Gets the utc time this insight was generated
/// </summary>
/// <remarks>
/// The algorithm framework handles setting this value appropriately.
/// If providing custom <see cref="Insight"/> implementation, be sure
/// to set this value to algorithm.UtcTime when the insight is generated.
/// </remarks>
public DateTime GeneratedTimeUtc { get; set; }
/// <summary>
/// Gets the insight's prediction end time. This is the time when this
/// insight prediction is expected to be fulfilled. This time takes into
/// account market hours, weekends, as well as the symbol's data resolution
/// </summary>
public DateTime CloseTimeUtc { get; set; }
/// <summary>
/// Gets the symbol this insight is for
/// </summary>
public Symbol Symbol { get; private set; }
/// <summary>
/// Gets the type of insight, for example, price insight or volatility insight
/// </summary>
public InsightType Type { get; private set; }
/// <summary>
/// Gets the initial reference value this insight is predicting against. The value is dependent on the specified <see cref="InsightType"/>
/// </summary>
public decimal ReferenceValue { get; set; }
/// <summary>
/// Gets the final reference value, used for scoring, this insight is predicting against. The value is dependent on the specified <see cref="InsightType"/>
/// </summary>
public decimal ReferenceValueFinal { get; set; }
/// <summary>
/// Gets the predicted direction, down, flat or up
/// </summary>
public InsightDirection Direction { get; private set; }
/// <summary>
/// Gets the period over which this insight is expected to come to fruition
/// </summary>
public TimeSpan Period { get; internal set; }
/// <summary>
/// Gets the predicted percent change in the insight type (price/volatility)
/// </summary>
public double? Magnitude { get; private set; }
/// <summary>
/// Gets the confidence in this insight
/// </summary>
public double? Confidence { get; private set; }
/// <summary>
/// Gets the portfolio weight of this insight
/// </summary>
public double? Weight { get; private set; }
/// <summary>
/// Gets the most recent scores for this insight
/// </summary>
public InsightScore Score { get; protected set; }
/// <summary>
/// Gets the estimated value of this insight in the account currency
/// </summary>
public decimal EstimatedValue { get; set; }
/// <summary>
/// The insight's tag containing additional information
/// </summary>
public string Tag { get; protected set; }
/// <summary>
/// Determines whether or not this insight is considered expired at the specified <paramref name="utcTime"/>
/// </summary>
/// <param name="utcTime">The algorithm's current time in UTC. See <see cref="IAlgorithm.UtcTime"/></param>
/// <returns>True if this insight is expired, false otherwise</returns>
public bool IsExpired(DateTime utcTime)
{
return CloseTimeUtc < utcTime;
}
/// <summary>
/// Determines whether or not this insight is considered active at the specified <paramref name="utcTime"/>
/// </summary>
/// <param name="utcTime">The algorithm's current time in UTC. See <see cref="IAlgorithm.UtcTime"/></param>
/// <returns>True if this insight is active, false otherwise</returns>
public bool IsActive(DateTime utcTime)
{
return !IsExpired(utcTime);
}
/// <summary>
/// Expire this insight
/// </summary>
/// <param name="utcTime">The algorithm's current time in UTC. See <see cref="IAlgorithm.UtcTime"/></param>
public void Expire(DateTime utcTime)
{
if (IsActive(utcTime))
{
CloseTimeUtc = utcTime.Add(-Time.OneSecond);
Period = CloseTimeUtc - GeneratedTimeUtc;
}
}
/// <summary>
/// Cancel this insight
/// </summary>
/// <param name="utcTime">The algorithm's current time in UTC. See <see cref="IAlgorithm.UtcTime"/></param>
public void Cancel(DateTime utcTime)
{
Expire(utcTime);
}
/// <summary>
/// Initializes a new instance of the <see cref="Insight"/> class
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="period">The period over which the prediction will come true</param>
/// <param name="type">The type of insight, price/volatility</param>
/// <param name="direction">The predicted direction</param>
/// <param name="tag">The insight's tag containing additional information</param>
public Insight(Symbol symbol, TimeSpan period, InsightType type, InsightDirection direction, string tag = "")
: this(symbol, period, type, direction, null, null, null, null, tag)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Insight"/> class
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="period">The period over which the prediction will come true</param>
/// <param name="type">The type of insight, price/volatility</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percentage change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">An identifier defining the model that generated this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
public Insight(Symbol symbol, TimeSpan period, InsightType type, InsightDirection direction, double? magnitude, double? confidence, string sourceModel = null, double? weight = null, string tag = "")
{
Id = Guid.NewGuid();
Score = new InsightScore();
SourceModel = sourceModel;
Symbol = symbol;
Type = type;
Direction = direction;
Period = period;
// Optional
Magnitude = magnitude;
Confidence = confidence;
Weight = weight;
Tag = tag;
_periodSpecification = new TimeSpanPeriodSpecification(period);
}
/// <summary>
/// Initializes a new instance of the <see cref="Insight"/> class
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="expiryFunc">Func that defines the expiry time</param>
/// <param name="type">The type of insight, price/volatility</param>
/// <param name="direction">The predicted direction</param>
/// <param name="tag">The insight's tag containing additional information</param>
public Insight(Symbol symbol, Func<DateTime, DateTime> expiryFunc, InsightType type, InsightDirection direction, string tag = "")
: this(symbol, expiryFunc, type, direction, null, null, null, null, tag)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Insight"/> class
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="expiryFunc">Func that defines the expiry time</param>
/// <param name="type">The type of insight, price/volatility</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percentage change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">An identifier defining the model that generated this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
public Insight(Symbol symbol, Func<DateTime, DateTime> expiryFunc, InsightType type, InsightDirection direction, double? magnitude, double? confidence, string sourceModel = null, double? weight = null, string tag = "")
: this(symbol, new FuncPeriodSpecification(expiryFunc), type, direction, magnitude, confidence, sourceModel, weight, tag)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Insight"/> class.
/// This constructor is provided mostly for testing purposes. When running inside an algorithm,
/// the generated and close times are set based on the algorithm's time.
/// </summary>
/// <param name="generatedTimeUtc">The time this insight was generated in utc</param>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="period">The period over which the prediction will come true</param>
/// <param name="type">The type of insight, price/volatility</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percentage change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">An identifier defining the model that generated this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
public Insight(DateTime generatedTimeUtc, Symbol symbol, TimeSpan period, InsightType type, InsightDirection direction, double? magnitude, double? confidence, string sourceModel = null, double? weight = null, string tag = "")
: this(symbol, period, type, direction, magnitude, confidence, sourceModel, weight, tag)
{
GeneratedTimeUtc = generatedTimeUtc;
CloseTimeUtc = generatedTimeUtc + period;
}
/// <summary>
/// Private constructor used to keep track of how a user defined the insight period.
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="periodSpec">A specification defining how the insight's period was defined, via time span, via resolution/barcount, via close time</param>
/// <param name="type">The type of insight, price/volatility</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percentage change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">An identifier defining the model that generated this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
private Insight(Symbol symbol, IPeriodSpecification periodSpec, InsightType type, InsightDirection direction, double? magnitude, double? confidence, string sourceModel = null, double? weight = null, string tag = "")
{
Id = Guid.NewGuid();
Score = new InsightScore();
SourceModel = sourceModel;
Symbol = symbol;
Type = type;
Direction = direction;
// Optional
Magnitude = magnitude;
Confidence = confidence;
Weight = weight;
Tag = tag;
_periodSpecification = periodSpec;
// keep existing behavior of Insight.Price such that we set the period immediately
var period = (periodSpec as TimeSpanPeriodSpecification)?.Period;
if (period != null)
{
Period = period.Value;
}
}
/// <summary>
/// Sets the insight period and close times if they have not already been set.
/// </summary>
/// <param name="exchangeHours">The insight's security exchange hours</param>
public void SetPeriodAndCloseTime(SecurityExchangeHours exchangeHours)
{
if (GeneratedTimeUtc == default(DateTime))
{
throw new InvalidOperationException(Messages.Insight.GeneratedTimeUtcNotSet(this));
}
_periodSpecification.SetPeriodAndCloseTime(this, exchangeHours);
}
/// <summary>
/// Creates a deep clone of this insight instance
/// </summary>
/// <returns>A new insight with identical values, but new instances</returns>
public virtual Insight Clone()
{
return new Insight(Symbol, Period, Type, Direction, Magnitude, Confidence, weight: Weight, tag: Tag)
{
GeneratedTimeUtc = GeneratedTimeUtc,
CloseTimeUtc = CloseTimeUtc,
Score = Score,
Id = Id,
EstimatedValue = EstimatedValue,
ReferenceValue = ReferenceValue,
ReferenceValueFinal = ReferenceValueFinal,
SourceModel = SourceModel,
GroupId = GroupId
};
}
/// <summary>
/// Creates a new insight for predicting the percent change in price over the specified period
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="resolution">The resolution used to define the insight's period and also used to determine the insight's close time</param>
/// <param name="barCount">The number of resolution time steps to make in market hours to compute the insight's closing time</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percent change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">The model generating this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
/// <returns>A new insight object for the specified parameters</returns>
public static Insight Price(Symbol symbol, Resolution resolution, int barCount, InsightDirection direction, double? magnitude = null, double? confidence = null, string sourceModel = null, double? weight = null, string tag = "")
{
if (barCount < 1)
{
throw new ArgumentOutOfRangeException(nameof(barCount), Messages.Insight.InvalidBarCount);
}
var spec = new ResolutionBarCountPeriodSpecification(resolution, barCount);
return new Insight(symbol, spec, InsightType.Price, direction, magnitude, confidence, sourceModel, weight, tag);
}
/// <summary>
/// Creates a new insight for predicting the percent change in price over the specified period
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="closeTimeLocal">The insight's closing time in the security's exchange time zone</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percent change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">The model generating this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
/// <returns>A new insight object for the specified parameters</returns>
public static Insight Price(Symbol symbol, DateTime closeTimeLocal, InsightDirection direction, double? magnitude = null, double? confidence = null, string sourceModel = null, double? weight = null, string tag = "")
{
var spec = closeTimeLocal == Time.EndOfTime ? (IPeriodSpecification)
new EndOfTimeCloseTimePeriodSpecification() : new CloseTimePeriodSpecification(closeTimeLocal);
return new Insight(symbol, spec, InsightType.Price, direction, magnitude, confidence, sourceModel, weight, tag);
}
/// <summary>
/// Creates a new insight for predicting the percent change in price over the specified period
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="period">The period over which the prediction will come true</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percent change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">The model generating this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
/// <returns>A new insight object for the specified parameters</returns>
public static Insight Price(Symbol symbol, TimeSpan period, InsightDirection direction, double? magnitude = null, double? confidence = null, string sourceModel = null, double? weight = null, string tag = "")
{
if (period < Time.OneSecond)
{
throw new ArgumentOutOfRangeException(nameof(period), Messages.Insight.InvalidPeriod);
}
var spec = period == Time.EndOfTimeTimeSpan ? (IPeriodSpecification)
new EndOfTimeCloseTimePeriodSpecification() : new TimeSpanPeriodSpecification(period);
return new Insight(symbol, spec, InsightType.Price, direction, magnitude, confidence, sourceModel, weight, tag);
}
/// <summary>
/// Creates a new insight for predicting the percent change in price over the specified period
/// </summary>
/// <param name="symbol">The symbol this insight is for</param>
/// <param name="expiryFunc">Func that defines the expiry time</param>
/// <param name="direction">The predicted direction</param>
/// <param name="magnitude">The predicted magnitude as a percent change</param>
/// <param name="confidence">The confidence in this insight</param>
/// <param name="sourceModel">The model generating this insight</param>
/// <param name="weight">The portfolio weight of this insight</param>
/// <param name="tag">The insight's tag containing additional information</param>
/// <returns>A new insight object for the specified parameters</returns>
public static Insight Price(Symbol symbol, Func<DateTime, DateTime> expiryFunc, InsightDirection direction, double? magnitude = null, double? confidence = null, string sourceModel = null, double? weight = null, string tag = "")
{
return new Insight(symbol, expiryFunc, InsightType.Price, direction, magnitude, confidence, sourceModel, weight, tag);
}
/// <summary>
/// Creates a new, unique group id and sets it on each insight
/// </summary>
/// <param name="insights">The insights to be grouped</param>
public static IEnumerable<Insight> Group(params Insight[] insights)
{
if (insights == null)
{
throw new ArgumentNullException(nameof(insights));
}
var groupId = Guid.NewGuid();
foreach (var insight in insights)
{
if (insight.GroupId.HasValue)
{
throw new InvalidOperationException(Messages.Insight.InsightAlreadyAssignedToAGroup(insight));
}
insight.GroupId = groupId;
}
return insights;
}
/// <summary>
/// Creates a new, unique group id and sets it on each insight
/// </summary>
/// <param name="insight">The insight to be grouped</param>
public static IEnumerable<Insight> Group(Insight insight) => Group(new[] {insight});
/// <summary>
/// Creates a new <see cref="Insight"/> object from the specified serialized form
/// </summary>
/// <param name="serializedInsight">The insight DTO</param>
/// <returns>A new insight containing the information specified</returns>
public static Insight FromSerializedInsight(SerializedInsight serializedInsight)
{
var sid = SecurityIdentifier.Parse(serializedInsight.Symbol);
var insight = new Insight(
Time.UnixTimeStampToDateTime(serializedInsight.CreatedTime),
new Symbol(sid, serializedInsight.Ticker ?? sid.Symbol),
TimeSpan.FromSeconds(serializedInsight.Period),
serializedInsight.Type,
serializedInsight.Direction,
serializedInsight.Magnitude,
serializedInsight.Confidence,
serializedInsight.SourceModel,
serializedInsight.Weight,
serializedInsight.Tag
)
{
Id = Guid.Parse(serializedInsight.Id),
CloseTimeUtc = Time.UnixTimeStampToDateTime(serializedInsight.CloseTime),
EstimatedValue = serializedInsight.EstimatedValue,
ReferenceValue = serializedInsight.ReferenceValue,
ReferenceValueFinal = serializedInsight.ReferenceValueFinal,
GroupId = string.IsNullOrEmpty(serializedInsight.GroupId) ? (Guid?) null : Guid.Parse(serializedInsight.GroupId)
};
// only set score values if non-zero or if they're the final scores
if (serializedInsight.ScoreIsFinal)
{
insight.Score.SetScore(InsightScoreType.Magnitude, serializedInsight.ScoreMagnitude, insight.CloseTimeUtc);
insight.Score.SetScore(InsightScoreType.Direction, serializedInsight.ScoreDirection, insight.CloseTimeUtc);
insight.Score.Finalize(insight.CloseTimeUtc);
}
else
{
if (serializedInsight.ScoreMagnitude != 0)
{
insight.Score.SetScore(InsightScoreType.Magnitude, serializedInsight.ScoreMagnitude, insight.CloseTimeUtc);
}
if (serializedInsight.ScoreDirection != 0)
{
insight.Score.SetScore(InsightScoreType.Direction, serializedInsight.ScoreDirection, insight.CloseTimeUtc);
}
}
return insight;
}
/// <summary>
/// Computes the insight closing time from the given generated time, resolution and bar count.
/// This will step through market hours using the given resolution, respecting holidays, early closes, weekends, etc..
/// </summary>
/// <param name="exchangeHours">The exchange hours of the insight's security</param>
/// <param name="generatedTimeUtc">The insight's generated time in utc</param>
/// <param name="resolution">The resolution used to 'step-through' market hours to compute a reasonable close time</param>
/// <param name="barCount">The number of resolution steps to take</param>
/// <returns>The insight's closing time in utc</returns>
public static DateTime ComputeCloseTime(SecurityExchangeHours exchangeHours, DateTime generatedTimeUtc, Resolution resolution, int barCount)
{
if (barCount < 1)
{
throw new ArgumentOutOfRangeException(nameof(barCount), Messages.Insight.InvalidBarCount);
}
// remap ticks to seconds
resolution = resolution == Resolution.Tick ? Resolution.Second : resolution;
if (resolution == Resolution.Hour)
{
// remap hours to minutes to avoid complications w/ stepping through
// for example 9->10 is an hour step but market opens at 9:30
barCount *= 60;
resolution = Resolution.Minute;
}
var barSize = resolution.ToTimeSpan();
var startTimeLocal = generatedTimeUtc.ConvertFromUtc(exchangeHours.TimeZone);
var closeTimeLocal = Time.GetEndTimeForTradeBars(exchangeHours, startTimeLocal, barSize, barCount, false);
return closeTimeLocal.ConvertToUtc(exchangeHours.TimeZone);
}
/// <summary>
/// computs the insight closing time from the given generated time and period
/// </summary>
/// <param name="exchangeHours">The exchange hours of the insight's security</param>
/// <param name="generatedTimeUtc">The insight's generated time in utc</param>
/// <param name="period">The insight's period</param>
/// <returns>The insight's closing time in utc</returns>
public static DateTime ComputeCloseTime(SecurityExchangeHours exchangeHours, DateTime generatedTimeUtc, TimeSpan period)
{
if (period < Time.OneSecond)
{
throw new ArgumentOutOfRangeException(nameof(period), Messages.Insight.InvalidPeriod);
}
var barSize = period.ToHigherResolutionEquivalent(false);
// remap ticks to seconds
barSize = barSize == Resolution.Tick ? Resolution.Second : barSize;
// remap hours to minutes to avoid complications w/ stepping through, for example 9->10 is an hour step but market opens at 9:30
barSize = barSize == Resolution.Hour ? Resolution.Minute : barSize;
var barCount = (int)(period.Ticks / barSize.ToTimeSpan().Ticks);
var closeTimeUtc = ComputeCloseTime(exchangeHours, generatedTimeUtc, barSize, barCount);
if (closeTimeUtc == generatedTimeUtc)
{
return ComputeCloseTime(exchangeHours, generatedTimeUtc, Resolution.Second, 1);
}
var totalPeriodUsed = barSize.ToTimeSpan().Multiply(barCount);
if (totalPeriodUsed != period)
{
var delta = period - totalPeriodUsed;
// interpret the remainder as fractional trading days
if (barSize == Resolution.Daily)
{
var percentOfDay = delta.Ticks / (double) Time.OneDay.Ticks;
delta = exchangeHours.RegularMarketDuration.Multiply(percentOfDay);
}
if (delta != TimeSpan.Zero)
{
// continue stepping forward using minute resolution for the remainder
barCount = (int) (delta.Ticks / Time.OneMinute.Ticks);
if (barCount > 0)
{
closeTimeUtc = ComputeCloseTime(exchangeHours, closeTimeUtc, Resolution.Minute, barCount);
}
}
}
return closeTimeUtc;
}
/// <summary>Returns a string that represents the current object.</summary>
/// <returns>A string that represents the current object.</returns>
/// <filterpriority>2</filterpriority>
public override string ToString()
{
return Messages.Insight.ToString(this);
}
/// <summary>
/// Returns a short string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
public string ShortToString()
{
return Messages.Insight.ShortToString(this);
}
/// <summary>
/// Distinguishes between the different ways an insight's period/close times can be specified
/// This was really only required since we can't properly acces certain data from within a static
/// context (such as Insight.Price) or from within a constructor w/out requiring the users to properly
/// fetch the required data and supply it as an argument.
/// </summary>
private interface IPeriodSpecification
{
void SetPeriodAndCloseTime(Insight insight, SecurityExchangeHours exchangeHours);
}
/// <summary>
/// User defined the insight's period using a time span
/// </summary>
private class TimeSpanPeriodSpecification : IPeriodSpecification
{
public readonly TimeSpan Period;
public TimeSpanPeriodSpecification(TimeSpan period)
{
if (period == TimeSpan.Zero)
{
period = Time.OneSecond;
}
Period = period;
}
public void SetPeriodAndCloseTime(Insight insight, SecurityExchangeHours exchangeHours)
{
insight.Period = Period;
insight.CloseTimeUtc = ComputeCloseTime(exchangeHours, insight.GeneratedTimeUtc, Period);
}
}
/// <summary>
/// User defined insight's period using a resolution and bar count
/// </summary>
private class ResolutionBarCountPeriodSpecification : IPeriodSpecification
{
public readonly Resolution Resolution;
public readonly int BarCount;
public ResolutionBarCountPeriodSpecification(Resolution resolution, int barCount)
{
if (resolution == Resolution.Tick)
{
resolution = Resolution.Second;
}
if (resolution == Resolution.Hour)
{
// remap hours to minutes to avoid errors w/ half hours, for example, 9:30 open
barCount *= 60;
resolution = Resolution.Minute;
}
Resolution = resolution;
BarCount = barCount;
}
public void SetPeriodAndCloseTime(Insight insight, SecurityExchangeHours exchangeHours)
{
insight.CloseTimeUtc = ComputeCloseTime(exchangeHours, insight.GeneratedTimeUtc, Resolution, BarCount);
insight.Period = insight.CloseTimeUtc - insight.GeneratedTimeUtc;
}
}
/// <summary>
/// User defined the insight's local closing time
/// </summary>
private class CloseTimePeriodSpecification : IPeriodSpecification
{
public readonly DateTime CloseTimeLocal;
public CloseTimePeriodSpecification(DateTime closeTimeLocal)
{
CloseTimeLocal = closeTimeLocal;
}
public void SetPeriodAndCloseTime(Insight insight, SecurityExchangeHours exchangeHours)
{
// Prevent close time to be defined to a date/time in closed market
var closeTimeLocal = exchangeHours.IsOpen(CloseTimeLocal, false)
? CloseTimeLocal
: exchangeHours.GetNextMarketOpen(CloseTimeLocal, false);
insight.CloseTimeUtc = closeTimeLocal.ConvertToUtc(exchangeHours.TimeZone);
if (insight.GeneratedTimeUtc > insight.CloseTimeUtc)
{
throw new ArgumentOutOfRangeException(nameof(closeTimeLocal), $"Insight closeTimeLocal must not be in the past.");
}
insight.Period = insight.CloseTimeUtc - insight.GeneratedTimeUtc;
}
}
/// <summary>
/// Special case for insights which close time is defined by a function
/// and want insights to expiry with calendar rules
/// </summary>
private class FuncPeriodSpecification : IPeriodSpecification
{
public readonly Func<DateTime, DateTime> _expiryFunc;
public FuncPeriodSpecification(Func<DateTime, DateTime> expiryFunc)
{
_expiryFunc = expiryFunc;
}
public void SetPeriodAndCloseTime(Insight insight, SecurityExchangeHours exchangeHours)
{
var closeTimeLocal = insight.GeneratedTimeUtc.ConvertFromUtc(exchangeHours.TimeZone);
closeTimeLocal = _expiryFunc(closeTimeLocal);
// Prevent close time to be defined to a date/time in closed market
if (!exchangeHours.IsOpen(closeTimeLocal, false))
{
closeTimeLocal = exchangeHours.GetNextMarketOpen(closeTimeLocal, false);
}
insight.CloseTimeUtc = closeTimeLocal.ConvertToUtc(exchangeHours.TimeZone);
insight.Period = insight.CloseTimeUtc - insight.GeneratedTimeUtc;
}
}
/// <summary>
/// Special case for insights where we do not know whats the
/// <see cref="Period"/> or <see cref="CloseTimeUtc"/>.
/// </summary>
private class EndOfTimeCloseTimePeriodSpecification : IPeriodSpecification
{
public void SetPeriodAndCloseTime(Insight insight, SecurityExchangeHours exchangeHours)
{
insight.Period = Time.EndOfTimeTimeSpan;
insight.CloseTimeUtc = Time.EndOfTime;
}
}
}
}
@@ -0,0 +1,395 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Linq;
using Python.Runtime;
using System.Collections;
using System.Collections.Generic;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Provides a collection for managing insights. This type provides collection access semantics
/// as well as dictionary access semantics through TryGetValue, ContainsKey, and this[symbol]
/// </summary>
public class InsightCollection : IEnumerable<Insight>
{
private int _totalInsightCount;
private int _openInsightCount;
private readonly List<Insight> _insightsComplete = new();
private readonly Dictionary<Symbol, List<Insight>> _insights = new();
/// <summary>
/// The open insight count
/// </summary>
public int Count
{
get
{
lock (_insights)
{
return _openInsightCount;
}
}
}
/// <summary>
/// The total insight count
/// </summary>
public int TotalCount
{
get
{
lock (_insights)
{
return _totalInsightCount;
}
}
}
/// <summary>Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</exception>
public void Add(Insight item)
{
lock (_insights)
{
_openInsightCount++;
_totalInsightCount++;
_insightsComplete.Add(item);
if (!_insights.TryGetValue(item.Symbol, out var existingInsights))
{
_insights[item.Symbol] = existingInsights = new();
}
existingInsights.Add(item);
}
}
/// <summary>
/// Adds each item in the specified enumerable of insights to this collection
/// </summary>
/// <param name="insights">The insights to add to this collection</param>
public void AddRange(IEnumerable<Insight> insights)
{
foreach (var insight in insights)
{
Add(insight);
}
}
/// <summary>Determines whether the <see cref="T:System.Collections.Generic.ICollection`1" /> contains a specific value.</summary>
/// <returns>true if <paramref name="item" /> is found in the <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false.</returns>
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
public bool Contains(Insight item)
{
lock(_insights)
{
return _insights.TryGetValue(item.Symbol, out var symbolInsights)
&& symbolInsights.Contains(item);
}
}
/// <summary>
/// Determines whether insights exist in this collection for the specified symbol
/// </summary>
/// <param name="symbol">The symbol key</param>
/// <returns>True if there are insights for the symbol in this collection</returns>
public bool ContainsKey(Symbol symbol)
{
lock (_insights)
{
return _insights.TryGetValue(symbol, out var symbolInsights)
&& symbolInsights.Count > 0;
}
}
/// <summary>Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
/// <returns>true if <paramref name="item" /> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false. This method also returns false if <paramref name="item" /> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1" />.</returns>
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</exception>
public bool Remove(Insight item)
{
lock (_insights)
{
if (_insights.TryGetValue(item.Symbol, out var symbolInsights))
{
if (symbolInsights.Remove(item))
{
_openInsightCount--;
// remove empty list from dictionary
if (symbolInsights.Count == 0)
{
_insights.Remove(item.Symbol);
}
return true;
}
}
}
return false;
}
/// <summary>
/// Dictionary accessor returns a list of insights for the specified symbol
/// </summary>
/// <param name="symbol">The symbol key</param>
/// <returns>List of insights for the symbol</returns>
public List<Insight> this[Symbol symbol]
{
get
{
lock(_insights)
{
return _insights[symbol]?.ToList();
}
}
set
{
lock (_insights)
{
if (_insights.TryGetValue(symbol, out var existingInsights))
{
_openInsightCount -= existingInsights?.Count ?? 0;
}
if (value != null)
{
_openInsightCount += value.Count;
_totalInsightCount += value.Count;
}
_insights[symbol] = value;
}
}
}
/// <summary>
/// Attempts to get the list of insights with the specified symbol key
/// </summary>
/// <param name="symbol">The symbol key</param>
/// <param name="insights">The insights for the specified symbol, or null if not found</param>
/// <returns>True if insights for the specified symbol were found, false otherwise</returns>
public bool TryGetValue(Symbol symbol, out List<Insight> insights)
{
lock (_insights)
{
var result = _insights.TryGetValue(symbol, out insights);
if (result)
{
// for thread safety we need to return a copy of the collection
insights = insights.ToList();
}
return result;
}
}
/// <summary>Returns an enumerator that iterates through the collection.</summary>
/// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<Insight> GetEnumerator()
{
lock (_insights)
{
return _insights.SelectMany(kvp => kvp.Value).ToList().GetEnumerator();
}
}
/// <summary>Returns an enumerator that iterates through a collection.</summary>
/// <returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Removes the symbol and its insights
/// </summary>
/// <param name="symbols">List of symbols that will be removed</param>
public void Clear(Symbol[] symbols)
{
lock (_insights)
{
foreach (var symbol in symbols)
{
if (_insights.Remove(symbol, out var existingInsights))
{
_openInsightCount -= existingInsights.Count;
}
}
}
}
/// <summary>
/// Gets the next expiry time UTC
/// </summary>
public DateTime? GetNextExpiryTime()
{
lock(_insights)
{
if (_openInsightCount == 0)
{
return null;
}
// we can't store expiration time because it can change
return _insights.Min(x => x.Value.Min(i => i.CloseTimeUtc));
}
}
/// <summary>
/// Gets the last generated active insight
/// </summary>
/// <returns>Collection of insights that are active</returns>
public ICollection<Insight> GetActiveInsights(DateTime utcTime)
{
var activeInsights = new List<Insight>();
lock (_insights)
{
foreach (var kvp in _insights)
{
foreach (var insight in kvp.Value)
{
if (insight.IsActive(utcTime))
{
activeInsights.Add(insight);
}
}
}
return activeInsights;
}
}
/// <summary>
/// Returns true if there are active insights for a given symbol and time
/// </summary>
/// <param name="symbol">The symbol key</param>
/// <param name="utcTime">Time that determines whether the insight has expired</param>
/// <returns></returns>
public bool HasActiveInsights(Symbol symbol, DateTime utcTime)
{
lock (_insights)
{
if(_insights.TryGetValue(symbol, out var existingInsights))
{
return existingInsights.Any(i => i.IsActive(utcTime));
}
}
return false;
}
/// <summary>
/// Remove all expired insights from the collection and retuns them
/// </summary>
/// <param name="utcTime">Time that determines whether the insight has expired</param>
/// <returns>Expired insights that were removed</returns>
public ICollection<Insight> RemoveExpiredInsights(DateTime utcTime)
{
var removedInsights = new List<Insight>();
lock (_insights)
{
foreach (var kvp in _insights)
{
foreach (var insight in kvp.Value)
{
if (insight.IsExpired(utcTime))
{
removedInsights.Add(insight);
}
}
}
foreach (var insight in removedInsights)
{
Remove(insight);
}
}
return removedInsights;
}
/// <summary>
/// Will remove insights from the complete insight collection
/// </summary>
/// <param name="filter">The function that will determine which insight to remove</param>
public void RemoveInsights(Func<Insight, bool> filter)
{
lock (_insights)
{
_insightsComplete.RemoveAll(insight => filter(insight));
// for consistentcy remove from open insights just in case
List<Insight> insightsToRemove = null;
foreach (var insights in _insights.Values)
{
foreach (var insight in insights)
{
if (filter(insight))
{
insightsToRemove ??= new ();
insightsToRemove.Add(insight);
}
}
}
if(insightsToRemove != null)
{
foreach (var insight in insightsToRemove)
{
Remove(insight);
}
}
}
}
/// <summary>
/// Will return insights from the complete insight collection
/// </summary>
/// <param name="filter">The function that will determine which insight to return</param>
/// <returns>A new list containing the selected insights</returns>
public List<Insight> GetInsights(Func<Insight, bool> filter = null)
{
lock (_insights)
{
if(filter == null)
{
return _insightsComplete.ToList();
}
return _insightsComplete.Where(filter).ToList();
}
}
/// <summary>
/// Will return insights from the complete insight collection
/// </summary>
/// <param name="filter">The function that will determine which insight to return</param>
/// <returns>A new list containing the selected insights</returns>
public List<Insight> GetInsights(PyObject filter)
{
Func<Insight, bool> convertedFilter;
if (filter.TrySafeAs(out convertedFilter))
{
return GetInsights(convertedFilter);
}
else
{
using (Py.GIL())
{
throw new ArgumentException($"InsightCollection.GetInsights: {filter.Repr()} is not a valid argument.");
}
}
}
}
}
@@ -0,0 +1,42 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Specifies the predicted direction for a insight (price/volatility)
/// </summary>
[JsonConverter(typeof(StringEnumConverter), true)]
public enum InsightDirection
{
/// <summary>
/// The value will go down (-1)
/// </summary>
Down = -1,
/// <summary>
/// The value will stay flat (0)
/// </summary>
Flat = 0,
/// <summary>
/// The value will go up (1)
/// </summary>
Up = 1
}
}
@@ -0,0 +1,136 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using Newtonsoft.Json;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Defines the scores given to a particular insight
/// </summary>
public class InsightScore
{
/// <summary>
/// Gets the time these scores were last updated
/// </summary>
[JsonProperty]
public DateTime UpdatedTimeUtc { get; private set; }
/// <summary>
/// Gets the direction score
/// </summary>
[JsonProperty]
public double Direction { get; private set; }
/// <summary>
/// Gets the magnitude score
/// </summary>
[JsonProperty]
public double Magnitude { get; private set; }
/// <summary>
/// Gets whether or not this is the insight's final score
/// </summary>
[JsonProperty]
public bool IsFinalScore { get; private set; }
/// <summary>
/// Initializes a new, default instance of the <see cref="InsightScore"/> class
/// </summary>
public InsightScore()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="InsightScore"/> class
/// </summary>
/// <param name="direction">The insight direction score</param>
/// <param name="magnitude">The insight percent change score</param>
/// <param name="updatedTimeUtc">The algorithm utc time these scores were computed</param>
public InsightScore(double direction, double magnitude, DateTime updatedTimeUtc)
{
Direction = direction;
Magnitude = magnitude;
UpdatedTimeUtc = updatedTimeUtc;
}
/// <summary>
/// Sets the specified score type with the value
/// </summary>
/// <param name="type">The score type to be set, Direction/Magnitude</param>
/// <param name="value">The new value for the score</param>
/// <param name="algorithmUtcTime">The algorithm's utc time at which time the new score was computed</param>
public void SetScore(InsightScoreType type, double value, DateTime algorithmUtcTime)
{
if (IsFinalScore) return;
UpdatedTimeUtc = algorithmUtcTime;
switch (type)
{
case InsightScoreType.Direction:
Direction = Math.Max(0, Math.Min(1, value));
break;
case InsightScoreType.Magnitude:
Magnitude = Math.Max(0, Math.Min(1, value));
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
/// <summary>
/// Marks the score as finalized, preventing any further updates.
/// </summary>
/// <param name="algorithmUtcTime">The algorithm's utc time at which time these scores were finalized</param>
public void Finalize(DateTime algorithmUtcTime)
{
IsFinalScore = true;
UpdatedTimeUtc = algorithmUtcTime;
}
/// <summary>
/// Gets the specified score
/// </summary>
/// <param name="type">The type of score to get, Direction/Magnitude</param>
/// <returns>The requested score</returns>
public double GetScore(InsightScoreType type)
{
switch (type)
{
case InsightScoreType.Direction:
return Direction;
case InsightScoreType.Magnitude:
return Magnitude;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
/// <summary>Returns a string that represents the current object.</summary>
/// <returns>A string that represents the current object.</returns>
/// <filterpriority>2</filterpriority>
public override string ToString()
{
return Messages.InsightScore.ToString(this);
}
}
}
@@ -0,0 +1,45 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using Python.Runtime;
using QuantConnect.Algorithm.Framework.Alphas.Analysis;
using QuantConnect.Python;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// A python implementation insight evaluator wrapper
/// </summary>
public class InsightScoreFunctionPythonWrapper : BasePythonWrapper<IInsightScoreFunction>, IInsightScoreFunction
{
/// <summary>
/// Creates a new python wrapper instance
/// </summary>
/// <param name="insightEvaluator">The python instance to wrap</param>
public InsightScoreFunctionPythonWrapper(PyObject insightEvaluator)
: base(insightEvaluator)
{
}
/// <summary>
/// Method to evaluate and score insights for each time step
/// </summary>
public void Score(InsightManager insightManager, DateTime utcTime)
{
InvokeMethod(nameof(Score), insightManager, utcTime);
}
}
}
@@ -0,0 +1,38 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Defines a specific type of score for a insight
/// </summary>
[JsonConverter(typeof(StringEnumConverter), true)]
public enum InsightScoreType
{
/// <summary>
/// Directional accuracy (0)
/// </summary>
Direction,
/// <summary>
/// Magnitude accuracy (1)
/// </summary>
Magnitude
}
}
@@ -0,0 +1,37 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Specifies the type of insight
/// </summary>
[JsonConverter(typeof(StringEnumConverter), true)]
public enum InsightType
{
/// <summary>
/// The insight is for a security's price (0)
/// </summary>
Price,
/// <summary>
/// The insight is for a security's price volatility (1)
/// </summary>
Volatility
}
}
@@ -0,0 +1,46 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using QuantConnect.Util;
namespace QuantConnect.Algorithm.Framework.Alphas.Serialization
{
/// <summary>
/// Defines how insights should be serialized to json
/// </summary>
public class InsightJsonConverter : TypeChangeJsonConverter<Insight, SerializedInsight>
{
/// <summary>
/// Convert the input value to a value to be serialized
/// </summary>
/// <param name="value">The input value to be converted before serialization</param>
/// <returns>A new instance of TResult that is to be serialized</returns>
protected override SerializedInsight Convert(Insight value)
{
return new SerializedInsight(value);
}
/// <summary>
/// Converts the input value to be deserialized
/// </summary>
/// <param name="value">The deserialized value that needs to be converted to T</param>
/// <returns>The converted value</returns>
protected override Insight Convert(SerializedInsight value)
{
return Insight.FromSerializedInsight(value);
}
}
}
@@ -0,0 +1,292 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Newtonsoft.Json;
using QuantConnect.Util;
using System;
namespace QuantConnect.Algorithm.Framework.Alphas.Serialization
{
/// <summary>
/// DTO used for serializing an insight that was just generated by an algorithm.
/// This type does not contain any of the analysis dependent fields, such as scores
/// and estimated value
/// </summary>
public class SerializedInsight
{
private double _createdTime;
/// <summary>
/// See <see cref="Insight.Id"/>
/// </summary>
public string Id { get; set; }
/// <summary>
/// See <see cref="Insight.GroupId"/>
/// </summary>
public string GroupId { get; set; }
/// <summary>
/// See <see cref="Insight.SourceModel"/>
/// </summary>
public string SourceModel { get; set; }
/// <summary>
/// Pass-through for <see cref="CreatedTime"/>
/// </summary>
[Obsolete("Deprecated as of 2020-01-23. Please use the `CreatedTime` property instead.")]
public double GeneratedTime
{
get { return _createdTime; }
set { _createdTime = value; }
}
/// <summary>
/// See <see cref="Insight.GeneratedTimeUtc"/>
/// </summary>
public double CreatedTime
{
get { return _createdTime; }
set { _createdTime = value; }
}
/// <summary>
/// See <see cref="Insight.CloseTimeUtc"/>
/// </summary>
public double CloseTime { get; set; }
/// <summary>
/// See <see cref="Insight.Symbol"/>
/// The symbol's security identifier string
/// </summary>
public string Symbol { get; set; }
/// <summary>
/// See <see cref="Insight.Symbol"/>
/// The symbol's ticker at the generated time
/// </summary>
public string Ticker { get; set; }
/// <summary>
/// See <see cref="Insight.Type"/>
/// </summary>
public InsightType Type { get; set; }
/// <summary>
/// See <see cref="Insight.ReferenceValue"/>
/// </summary>
[JsonProperty("reference")]
public decimal ReferenceValue { get; set; }
/// <summary>
/// See <see cref="Insight.ReferenceValueFinal"/>
/// </summary>
public decimal ReferenceValueFinal { get; set; }
/// <summary>
/// See <see cref="Insight.Direction"/>
/// </summary>
public InsightDirection Direction { get; set; }
/// <summary>
/// See <see cref="Insight.Period"/>
/// </summary>
public double Period { get; set; }
/// <summary>
/// See <see cref="Insight.Magnitude"/>
/// </summary>
[JsonConverter(typeof(JsonRoundingConverter))]
public double? Magnitude { get; set; }
/// <summary>
/// See <see cref="Insight.Confidence"/>
/// </summary>
[JsonConverter(typeof(JsonRoundingConverter))]
public double? Confidence { get; set; }
/// <summary>
/// See <see cref="Insight.Weight"/>
/// </summary>
public double? Weight { get; set; }
/// <summary>
/// See <see cref="InsightScore.IsFinalScore"/>
/// </summary>
public bool ScoreIsFinal { get; set; }
/// <summary>
/// See <see cref="InsightScore.Magnitude"/>
/// </summary>
[JsonConverter(typeof(JsonRoundingConverter))]
public double ScoreMagnitude { get; set; }
/// <summary>
/// See <see cref="InsightScore.Direction"/>
/// </summary>
[JsonConverter(typeof(JsonRoundingConverter))]
public double ScoreDirection { get; set; }
/// <summary>
/// See <see cref="Insight.EstimatedValue"/>
/// </summary>
[JsonConverter(typeof(JsonRoundingConverter))]
public decimal EstimatedValue { get; set; }
/// <summary>
/// See <see cref="Insight.Tag"/>
/// </summary>
public string Tag { get; set; }
/// <summary>
/// Initializes a new default instance of the <see cref="SerializedInsight"/> class
/// </summary>
public SerializedInsight()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SerializedInsight "/> class by copying the specified insight
/// </summary>
/// <param name="insight">The insight to copy</param>
public SerializedInsight(Insight insight)
{
Id = insight.Id.ToStringInvariant("N");
SourceModel = insight.SourceModel;
GroupId = insight.GroupId?.ToStringInvariant("N");
CreatedTime = Time.DateTimeToUnixTimeStamp(insight.GeneratedTimeUtc);
CloseTime = Time.DateTimeToUnixTimeStamp(insight.CloseTimeUtc);
Symbol = insight.Symbol.ID.ToString();
Ticker = insight.Symbol.Value;
Type = insight.Type;
ReferenceValue = insight.ReferenceValue;
ReferenceValueFinal = insight.ReferenceValueFinal;
Direction = insight.Direction;
Period = insight.Period.TotalSeconds;
Magnitude = insight.Magnitude;
Confidence = insight.Confidence;
ScoreIsFinal = insight.Score.IsFinalScore;
ScoreMagnitude = insight.Score.Magnitude;
ScoreDirection = insight.Score.Direction;
EstimatedValue = insight.EstimatedValue;
Weight = insight.Weight;
Tag = insight.Tag;
}
#region BackwardsCompatibility
[JsonProperty("group-id")]
string OldGroupId
{
set
{
GroupId = value;
}
}
[JsonProperty("source-model")]
string OldSourceModel
{
set
{
SourceModel = value;
}
}
/// <summary>
/// Pass-through for <see cref="CreatedTime"/>
/// </summary>
[JsonProperty("generated-time")]
double OldGeneratedTime
{
set
{
GeneratedTime = value;
}
}
/// <summary>
/// See <see cref="Insight.GeneratedTimeUtc"/>
/// </summary>
[JsonProperty("created-time")]
public double OldCreatedTime
{
set
{
CreatedTime = value;
}
}
/// <summary>
/// See <see cref="Insight.CloseTimeUtc"/>
/// </summary>
[JsonProperty("close-time")]
public double OldCloseTime
{
set
{
CloseTime = value;
}
}
[JsonProperty("reference-final")]
decimal OldReferenceValueFinal
{
set
{
ReferenceValueFinal = value;
}
}
[JsonProperty("score-final")]
bool OldScoreIsFinal
{
set
{
ScoreIsFinal = value;
}
}
[JsonProperty("score-magnitude")]
[JsonConverter(typeof(JsonRoundingConverter))]
double OldScoreMagnitude
{
set
{
ScoreMagnitude = value;
}
}
[JsonProperty("score-direction")]
[JsonConverter(typeof(JsonRoundingConverter))]
double OldScoreDirection
{
set
{
ScoreDirection = value;
}
}
[JsonProperty("estimated-value")]
[JsonConverter(typeof(JsonRoundingConverter))]
decimal OldEstimatedValue
{
set
{
EstimatedValue = value;
}
}
#endregion
}
}