Commit Graph

30 Commits

Author SHA1 Message Date
Martin Molinero 64d43c1487 Add Insight.ReferenceValueFinal 2019-07-09 17:53:58 -03:00
Martin Molinero ee4f8fee82 Overall performance improvements
- `TimeSliceFactory` will avoid creating empty collections
- `ExecutionModels` will check target collection count before trying to
enumerate
- Reduce calls to .`TotalPortfolioValue`
- `SecurityValues` will only be created when required
- `TimeKeeper` will use TimeZone unique Id as dictionary key. The
TimeZone hash is expensive.
- `AlgorithmManager` will avoid calling `DateTime.UtcNow`,
`ConvertFromUtc()` and `RoundDownInTimeZone()`
2019-06-03 15:09:02 -03:00
Jared ffcee5bd73 Merge pull request #3211 from Martin-Molinero/bug-3155-insightmanager-thread-safety
Make InsightManager thread safe
2019-05-29 07:09:47 -07:00
Martin Molinero e294b3c3e2 Fix overflow exception
- Adding new `AlgorithmSettings` Min and Max absolute portfolio target
percentage
- Adding new `PortfolioConstructionModel.FilterInvalidInsightMagnitude()`
helper method that will be used by the `BlackLitterman` and
`MeanVariance` optiomization portfolio construction models to skip
insights with extreme magnitudes that will cause exceptions
- `PortfolioTarget.Percentage()` will now verify requested percent is
withing the settings values
2019-05-23 20:30:44 -03:00
Martin Molinero 1fc2ef11a3 Make InsightManager thread safe
- Adding new `lock` so that `InsightManager` `Step()`,
`AllInsights`, `ContextsOpenAt()`, `GetUpdatedContexts()`
and `OpenInsights` are thread safe.
2019-05-20 15:35:59 -03:00
Martin Molinero c39638668c Overall performance improvements
- `FactorFile` will keep an ordered reversed list with the dates.
Calling `Reverse()` on the `SortedList` is expensive.
- `MapFiles` will keep first and last date, so we don't need to call
`First()` and `Last()` multiple times.
- `Liquidate` will go through all the algorithms securities only if
necessary
- `TradeBar` parsing will not call `new T` for pure `TradeBar` which is
expensive
- Removing `Lazy` hash code and security type for the
`SecurityIdentifier`, replacing for direct initialization. Accessing the
`Lazy` value adds an overhead.
- Replacing `Enum` to string for hardcoded switch statement. `Enum.ToString` is expensive.
- `DataManager` will be lazy for counting the subscriptions for
determining if its above the limit
- Adding `AlgorithmSecurityValuesProvider.GetAllValues()`, removes the
need to fetch all the security keys twice.
- During universe selection, will not try to re add already added symbol
2019-04-22 10:47:27 -03:00
Martin Molinero 938047de47 Will ignore flat insights
- `Flat` insights will be ignored both for scoring (`InsightManager`)
and for statistics (`StatisticsInsightManagerExtension`). Adding unit
tests
2019-04-16 20:39:55 -03:00
Martin Molinero b7930aff67 Performance improvements
- Using `Aggregate(lambda)` vs `Sum(lambda)` since the later is slower
due to performing an extra `Select`
- For `QCAlgorithm.Framework.OnFrameworkData()` will avoid calling
`ToArray()` on empty `Enumerables` due to its cost * the number of
calls. If the `Enumerable` is the empty instance, which is static,
will create a new empty array and return it instead.
- Replacing `SecurityIdentifier` `SecurityType` and `GetHashCode`
implementations for `Lazy` versions, that are performed just once, since
these values do not change and are used multiple times.
- For the different `DataDictionary<T>` implementations adding `this[
Symbol] get; set` since existing overload `this [string]` produces an
extra round operations `Symbol->string->Symbol` with a significant
impact.
- Adding `PortfolioTargetCollection.AddRange()` overload using an array
to avoid unnecessary convertions.
2019-04-11 19:01:27 -03:00
Martin Molinero 9d5b1f5be6 Fix auto generated insight period
- Updating regression test to assert of period value
2019-03-28 18:43:09 -03:00
Jared 9bf537a9b3 Merge pull request #3030 from QuantConnect/feature-3029-order-based-insight-autogeneration
Emiting Insights based on Order Fills
2019-03-28 10:04:54 -07:00
Martin Molinero 5b04cfe202 Emiting Insights based on Fills
- Classic Algorithms will emight insights based on order fills.
   - To be able to update generated insights closed time, we will not
   clone emitted insights.
   - `InsightAnalysisContext` will update `AnalysisEndTimeUtc` when the
   Insight period is closed and the period is `EndOfTimeTimeSpan`
- Adding new regression algorithm asserting on the new emitted insights
- Adding unit tests
- `LiveTradingResultHandler` will store `AlphaRunTimeStatistics`
- Making `DefaultAlphaHandler.ProcessAsynchronousEvents` virtual to
facilitate cloud changes
2019-03-26 16:09:22 -03:00
Martin Molinero 7d1777d364 Ignore Flat Insights direction scoring
- We will ignore flat insights direction scoring
2019-03-21 14:43:48 -03:00
Michael Handschuh 4fd16f6daf Fix resolution of insight close times, allow user defined close times
Fixes a bug where we were using the security's data resolution to compute
the insight's close time. This led a case such as insight.Period == 20days
to step 20days worth of tradable minutes (assuming minute data resolution),
yielding a close time that was very far in the future.

We also add different means of specifying an insight's period/close time:
1. Specify insight period as a TimeSpan and we compute close time
2. Specify insight period and a resolution and bar count and we compute close time
3. Specify insight close time local directly and we compute the insight period

The key here is maintaining consistency between the three different approaches
which is heavily validated with the corresponding unit tests.

Edits also made to trust the insight's close time as the analysis end time in
the case where the analysis period == insight period (extra analysis period = 0).
Given the current setup (extra analysis period == 0), this guarantees that close
and analysis end times are equivalent.

Regression statistics were updated and expectedly we get many more insights that
have completed analysis, and as such, average scores have also changed.
2018-08-07 11:21:11 -04:00
Michael Handschuh 728868d46f Remove incorrect insight closing time approximation
The insight itself defines when it closes via the algorithm framework
and properly takes into account weekends and out of market hours. The
insight analysis was not respecting the insight's stated close time,
but instead was simply doing generated time + period, which doesn't
properly take into account market hours. This causes the number of
closed insights to decrease and due to the extra time for each insight,
the values of the insights have also increased.
2018-04-23 13:11:06 -04:00
Michael Handschuh dd764ad8e9 Rename InsightCollection->GeneratedInsightsCollection
This type is just used as a container for generatd insights. Renaming in
preparation for a new InsightCollection to mirror the PortfolioTargetCollection
2018-04-10 19:24:36 -04:00
Michael Handschuh 708b0e91b8 Dispose of InsightManager extensions on exit
This isn't technically required, but it's best practice to explicitly
dispose of resources that require it.
2018-03-22 14:51:42 -04:00
Michael Handschuh 6b239674e2 Renames Alpha -> Insight
The term 'alpha' is used to describe the entire algorithm. Therefore, 'alpha'
produces insights. From this we have things like IAlphaModel, which is the model
defining how insights are produced. We have IAlphaHandler, which defines how the
insights from a single 'alpha' (the algorithm) are managed, analyzed, and stored.
Types closer to the individual prediction level, such as InsightDirection, or
InsightScore relate directly to exactly 1 insight. The distinction between the
two became more clear as we developed the insights API, and from that effort it
was decided to harmonize alpha/insight terminology across the various QC systems.
2018-03-09 16:12:56 -05:00
Michael Handschuh d461544b21 Enforce deterministic scoring by using deterministic enumerables
This change fixes the non-determinism seen in the rolling averaged alpha scores. This was
caused by usage of ConcurrentDictionary coupled with the key being a new guid. The new guid
was the source of non-determinism as it caused the same conceptual alpha from backtest A to
end up in a different 'bucket' on backtest B due to a different guid. The concurrency isn't
actually needed or desirable in this context. The AlphaManager must be invoked synchronously
to avoid inconsistent/non-deterministic analysis. Given this, the collections were changed
to use HashSet<T> and now produces deterministic results independent of the alpha's id.
2018-01-12 12:08:40 -05:00
Michael Handschuh 69d3a10a93 Decompose DefaultAlphaHandler into IAlphaManagerExtension
The IAlphaManagerExtension defines a type that needs to react to events produced
by the AlphaManager. The actual events were removed in favor of a interface to
handle the events. This removes the need to wire events and instead just pass the
extensions to the alph manager and it will handle invoking the extensions at the
appropriate time.

This change removes all charting and statistics aggregation logic from the alpha
handler and moves it into dedicated types, AlphaChartingManagerExtension and
AlphaStatisticsManagerExtension. The resulting types are highly decoupled from the
LEAN ecosystem allowing them to be easily unit tested, whereas before the logic
was embedded in a handler with many many dependencies which would be very hard to
properly unit test.

As part of this change (and in preparation for moving scoring to the alpha thread)
the resolution of SecurityValues was removed from the alpha manager. In this new
pattern, the alpha manager is pushed generated alphas and security values at each
time step.
2018-01-12 12:08:40 -05:00
Michael Handschuh cfea54aecd Fixes average estimated value and delays avg score sampling 2017-12-28 12:24:59 -05:00
Michael Handschuh b07928bd58 Properly account for market hours in alpha prediction periods
If we make a prediction for 1 day in the future, we actually mean 1 trading day.
This change updates the alpha analysis logic to take into account the security's
market hours.
2017-12-28 11:27:41 -05:00
Michael Handschuh 45f97d38e9 Remove ConcurrentDictionary.IsEmpty call
It turns out that checking if it's empty is much more expensive than enumerating
an empty collection. This is because IsEmpty acquires all the locks in order to
give a 'snapshot' answer. Enumerating the dictionary directly (not .Keys or .Values)
instead acquires a single finer grained lock at a time. IIRC, one lock will manage a
few buckets internally.
2017-12-28 11:27:41 -05:00
Michael Handschuh 3bfd567009 Properly seed ema of population scores
Not seeding this value cause a very heavy 0 starting value to keep the average
suppressed throughout the entire backtest, or until enough alphas are generated
to overcome the initial ema seed value.
2017-12-28 11:27:40 -05:00
Michael Handschuh dfce99f575 Sample alpha scores on next time step, ignore mag scores if mag=null 2017-12-28 11:27:40 -05:00
Michael Handschuh a2481387cd Directly enumerator concurrent dictonary instead of values
Enumerating the values directly requires the dictionary to acquire all global locks
vs enumerating the dictionary's key values pairs uses fine-grained locking at the
bucket level.
2017-12-20 10:44:56 -05:00
Michael Handschuh 2295e524f4 Add IAlphaRuntimeStatisticsGenerator and send to result handler
Provides estimates of alpha value as well as performs online computations of
alpha scores and other KPIs.

Sends alpha stats to result handler
Update live result with framework flag
2017-12-20 08:33:30 -05:00
Michael Handschuh 5a81bce5f6 Add volume and quote currency conversion to SecurityValues 2017-12-20 08:06:30 -05:00
Michael Handschuh 5337cb0b5e Fixes reporting of finalized alpha scores 2017-12-19 18:18:33 -05:00
Michael Handschuh 3161fd600b Rename PercentChange -> Magnitude 2017-12-15 20:10:34 -05:00
Michael Handschuh b4b3aae112 Rename Signal -> Alpha
Whoa... I think I got everything :)
2017-12-15 18:24:58 -05:00