cleanup and refactoring
@@ -121,3 +121,5 @@ fix-bullets.ps1
|
||||
fix_bullets.py
|
||||
fix_read.py
|
||||
.aider*
|
||||
|
||||
sandbox/**
|
||||
@@ -1,314 +0,0 @@
|
||||
|
||||
SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS
|
||||
|
||||
Commands marked with * may be preceded by a number, _N.
|
||||
Notes in parentheses indicate the behavior if _N is given.
|
||||
A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K.
|
||||
|
||||
h H Display this help.
|
||||
q :q Q :Q ZZ Exit.
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
MMOOVVIINNGG
|
||||
|
||||
e ^E j ^N CR * Forward one line (or _N lines).
|
||||
y ^Y k ^K ^P * Backward one line (or _N lines).
|
||||
f ^F ^V SPACE * Forward one window (or _N lines).
|
||||
b ^B ESC-v * Backward one window (or _N lines).
|
||||
z * Forward one window (and set window to _N).
|
||||
w * Backward one window (and set window to _N).
|
||||
ESC-SPACE * Forward one window, but don't stop at end-of-file.
|
||||
d ^D * Forward one half-window (and set half-window to _N).
|
||||
u ^U * Backward one half-window (and set half-window to _N).
|
||||
ESC-) RightArrow * Right one half screen width (or _N positions).
|
||||
ESC-( LeftArrow * Left one half screen width (or _N positions).
|
||||
ESC-} ^RightArrow Right to last column displayed.
|
||||
ESC-{ ^LeftArrow Left to first column.
|
||||
F Forward forever; like "tail -f".
|
||||
ESC-F Like F but stop when search pattern is found.
|
||||
r ^R ^L Repaint screen.
|
||||
R Repaint screen, discarding buffered input.
|
||||
---------------------------------------------------
|
||||
Default "window" is the screen height.
|
||||
Default "half-window" is half of the screen height.
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
SSEEAARRCCHHIINNGG
|
||||
|
||||
/_p_a_t_t_e_r_n * Search forward for (_N-th) matching line.
|
||||
?_p_a_t_t_e_r_n * Search backward for (_N-th) matching line.
|
||||
n * Repeat previous search (for _N-th occurrence).
|
||||
N * Repeat previous search in reverse direction.
|
||||
ESC-n * Repeat previous search, spanning files.
|
||||
ESC-N * Repeat previous search, reverse dir. & spanning files.
|
||||
^O^N ^On * Search forward for (_N-th) OSC8 hyperlink.
|
||||
^O^P ^Op * Search backward for (_N-th) OSC8 hyperlink.
|
||||
^O^L ^Ol Jump to the currently selected OSC8 hyperlink.
|
||||
ESC-u Undo (toggle) search highlighting.
|
||||
ESC-U Clear search highlighting.
|
||||
&_p_a_t_t_e_r_n * Display only matching lines.
|
||||
---------------------------------------------------
|
||||
A search pattern may begin with one or more of:
|
||||
^N or ! Search for NON-matching lines.
|
||||
^E or * Search multiple files (pass thru END OF FILE).
|
||||
^F or @ Start search at FIRST file (for /) or last file (for ?).
|
||||
^K Highlight matches, but don't move (KEEP position).
|
||||
^R Don't use REGULAR EXPRESSIONS.
|
||||
^S _n Search for match in _n-th parenthesized subpattern.
|
||||
^W WRAP search if no match found.
|
||||
^L Enter next character literally into pattern.
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
JJUUMMPPIINNGG
|
||||
|
||||
g < ESC-< * Go to first line in file (or line _N).
|
||||
G > ESC-> * Go to last line in file (or line _N).
|
||||
p % * Go to beginning of file (or _N percent into file).
|
||||
t * Go to the (_N-th) next tag.
|
||||
T * Go to the (_N-th) previous tag.
|
||||
{ ( [ * Find close bracket } ) ].
|
||||
} ) ] * Find open bracket { ( [.
|
||||
ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>.
|
||||
ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_>.
|
||||
---------------------------------------------------
|
||||
Each "find close bracket" command goes forward to the close bracket
|
||||
matching the (_N-th) open bracket in the top line.
|
||||
Each "find open bracket" command goes backward to the open bracket
|
||||
matching the (_N-th) close bracket in the bottom line.
|
||||
|
||||
m_<_l_e_t_t_e_r_> Mark the current top line with <letter>.
|
||||
M_<_l_e_t_t_e_r_> Mark the current bottom line with <letter>.
|
||||
'_<_l_e_t_t_e_r_> Go to a previously marked position.
|
||||
'' Go to the previous position.
|
||||
^X^X Same as '.
|
||||
ESC-m_<_l_e_t_t_e_r_> Clear a mark.
|
||||
---------------------------------------------------
|
||||
A mark is any upper-case or lower-case letter.
|
||||
Certain marks are predefined:
|
||||
^ means beginning of the file
|
||||
$ means end of the file
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
CCHHAANNGGIINNGG FFIILLEESS
|
||||
|
||||
:e [_f_i_l_e] Examine a new file.
|
||||
^X^V Same as :e.
|
||||
:n * Examine the (_N-th) next file from the command line.
|
||||
:p * Examine the (_N-th) previous file from the command line.
|
||||
:x * Examine the first (or _N-th) file from the command line.
|
||||
^O^O Open the currently selected OSC8 hyperlink.
|
||||
:d Delete the current file from the command line list.
|
||||
= ^G :f Print current file name.
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
MMIISSCCEELLLLAANNEEOOUUSS CCOOMMMMAANNDDSS
|
||||
|
||||
-_<_f_l_a_g_> Toggle a command line option [see OPTIONS below].
|
||||
--_<_n_a_m_e_> Toggle a command line option, by name.
|
||||
__<_f_l_a_g_> Display the setting of a command line option.
|
||||
___<_n_a_m_e_> Display the setting of an option, by name.
|
||||
+_c_m_d Execute the less cmd each time a new file is examined.
|
||||
|
||||
!_c_o_m_m_a_n_d Execute the shell command with $SHELL.
|
||||
#_c_o_m_m_a_n_d Execute the shell command, expanded like a prompt.
|
||||
|XX_c_o_m_m_a_n_d Pipe file between current pos & mark XX to shell command.
|
||||
s _f_i_l_e Save input to a file.
|
||||
v Edit the current file with $VISUAL or $EDITOR.
|
||||
V Print version number of "less".
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
OOPPTTIIOONNSS
|
||||
|
||||
Most options may be changed either on the command line,
|
||||
or from within less by using the - or -- command.
|
||||
Options may be given in one of two forms: either a single
|
||||
character preceded by a -, or a name preceded by --.
|
||||
|
||||
-? ........ --help
|
||||
Display help (from command line).
|
||||
-a ........ --search-skip-screen
|
||||
Search skips current screen.
|
||||
-A ........ --SEARCH-SKIP-SCREEN
|
||||
Search starts just after target line.
|
||||
-b [_N] .... --buffers=[_N]
|
||||
Number of buffers.
|
||||
-B ........ --auto-buffers
|
||||
Don't automatically allocate buffers for pipes.
|
||||
-c ........ --clear-screen
|
||||
Repaint by clearing rather than scrolling.
|
||||
-d ........ --dumb
|
||||
Dumb terminal.
|
||||
-D xx_c_o_l_o_r . --color=xx_c_o_l_o_r
|
||||
Set screen colors.
|
||||
-e -E .... --quit-at-eof --QUIT-AT-EOF
|
||||
Quit at end of file.
|
||||
-f ........ --force
|
||||
Force open non-regular files.
|
||||
-F ........ --quit-if-one-screen
|
||||
Quit if entire file fits on first screen.
|
||||
-g ........ --hilite-search
|
||||
Highlight only last match for searches.
|
||||
-G ........ --HILITE-SEARCH
|
||||
Don't highlight any matches for searches.
|
||||
-h [_N] .... --max-back-scroll=[_N]
|
||||
Backward scroll limit.
|
||||
-i ........ --ignore-case
|
||||
Ignore case in searches that do not contain uppercase.
|
||||
-I ........ --IGNORE-CASE
|
||||
Ignore case in all searches.
|
||||
-j [_N] .... --jump-target=[_N]
|
||||
Screen position of target lines.
|
||||
-J ........ --status-column
|
||||
Display a status column at left edge of screen.
|
||||
-k _f_i_l_e ... --lesskey-file=_f_i_l_e
|
||||
Use a compiled lesskey file.
|
||||
-K ........ --quit-on-intr
|
||||
Exit less in response to ctrl-C.
|
||||
-L ........ --no-lessopen
|
||||
Ignore the LESSOPEN environment variable.
|
||||
-m -M .... --long-prompt --LONG-PROMPT
|
||||
Set prompt style.
|
||||
-n ......... --line-numbers
|
||||
Suppress line numbers in prompts and messages.
|
||||
-N ......... --LINE-NUMBERS
|
||||
Display line number at start of each line.
|
||||
-o [_f_i_l_e] .. --log-file=[_f_i_l_e]
|
||||
Copy to log file (standard input only).
|
||||
-O [_f_i_l_e] .. --LOG-FILE=[_f_i_l_e]
|
||||
Copy to log file (unconditionally overwrite).
|
||||
-p _p_a_t_t_e_r_n . --pattern=[_p_a_t_t_e_r_n]
|
||||
Start at pattern (from command line).
|
||||
-P [_p_r_o_m_p_t] --prompt=[_p_r_o_m_p_t]
|
||||
Define new prompt.
|
||||
-q -Q .... --quiet --QUIET --silent --SILENT
|
||||
Quiet the terminal bell.
|
||||
-r -R .... --raw-control-chars --RAW-CONTROL-CHARS
|
||||
Output "raw" control characters.
|
||||
-s ........ --squeeze-blank-lines
|
||||
Squeeze multiple blank lines.
|
||||
-S ........ --chop-long-lines
|
||||
Chop (truncate) long lines rather than wrapping.
|
||||
-t _t_a_g .... --tag=[_t_a_g]
|
||||
Find a tag.
|
||||
-T [_t_a_g_s_f_i_l_e] --tag-file=[_t_a_g_s_f_i_l_e]
|
||||
Use an alternate tags file.
|
||||
-u -U .... --underline-special --UNDERLINE-SPECIAL
|
||||
Change handling of backspaces, tabs and carriage returns.
|
||||
-V ........ --version
|
||||
Display the version number of "less".
|
||||
-w ........ --hilite-unread
|
||||
Highlight first new line after forward-screen.
|
||||
-W ........ --HILITE-UNREAD
|
||||
Highlight first new line after any forward movement.
|
||||
-x [_N[,...]] --tabs=[_N[,...]]
|
||||
Set tab stops.
|
||||
-X ........ --no-init
|
||||
Don't use termcap init/deinit strings.
|
||||
-y [_N] .... --max-forw-scroll=[_N]
|
||||
Forward scroll limit.
|
||||
-z [_N] .... --window=[_N]
|
||||
Set size of window.
|
||||
-" [_c[_c]] . --quotes=[_c[_c]]
|
||||
Set shell quote characters.
|
||||
-~ ........ --tilde
|
||||
Don't display tildes after end of file.
|
||||
-# [_N] .... --shift=[_N]
|
||||
Set horizontal scroll amount (0 = one half screen width).
|
||||
|
||||
--exit-follow-on-close
|
||||
Exit F command on a pipe when writer closes pipe.
|
||||
--file-size
|
||||
Automatically determine the size of the input file.
|
||||
--follow-name
|
||||
The F command changes files if the input file is renamed.
|
||||
--header=[_L[,_C[,_N]]]
|
||||
Use _L lines (starting at line _N) and _C columns as headers.
|
||||
--incsearch
|
||||
Search file as each pattern character is typed in.
|
||||
--intr=[_C]
|
||||
Use _C instead of ^X to interrupt a read.
|
||||
--lesskey-context=_t_e_x_t
|
||||
Use lesskey source file contents.
|
||||
--lesskey-src=_f_i_l_e
|
||||
Use a lesskey source file.
|
||||
--line-num-width=[_N]
|
||||
Set the width of the -N line number field to _N characters.
|
||||
--match-shift=[_N]
|
||||
Show at least _N characters to the left of a search match.
|
||||
--modelines=[_N]
|
||||
Read _N lines from the input file and look for vim modelines.
|
||||
--mouse
|
||||
Enable mouse input.
|
||||
--no-keypad
|
||||
Don't send termcap keypad init/deinit strings.
|
||||
--no-histdups
|
||||
Remove duplicates from command history.
|
||||
--no-number-headers
|
||||
Don't give line numbers to header lines.
|
||||
--no-search-header-lines
|
||||
Searches do not include header lines.
|
||||
--no-search-header-columns
|
||||
Searches do not include header columns.
|
||||
--no-search-headers
|
||||
Searches do not include header lines or columns.
|
||||
--no-vbell
|
||||
Disable the terminal's visual bell.
|
||||
--redraw-on-quit
|
||||
Redraw final screen when quitting.
|
||||
--rscroll=[_C]
|
||||
Set the character used to mark truncated lines.
|
||||
--save-marks
|
||||
Retain marks across invocations of less.
|
||||
--search-options=[EFKNRW-]
|
||||
Set default options for every search.
|
||||
--show-preproc-errors
|
||||
Display a message if preprocessor exits with an error status.
|
||||
--proc-backspace
|
||||
Process backspaces for bold/underline.
|
||||
--PROC-BACKSPACE
|
||||
Treat backspaces as control characters.
|
||||
--proc-return
|
||||
Delete carriage returns before newline.
|
||||
--PROC-RETURN
|
||||
Treat carriage returns as control characters.
|
||||
--proc-tab
|
||||
Expand tabs to spaces.
|
||||
--PROC-TAB
|
||||
Treat tabs as control characters.
|
||||
--status-col-width=[_N]
|
||||
Set the width of the -J status column to _N characters.
|
||||
--status-line
|
||||
Highlight or color the entire line containing a mark.
|
||||
--use-backslash
|
||||
Subsequent options use backslash as escape char.
|
||||
--use-color
|
||||
Enables colored text.
|
||||
--wheel-lines=[_N]
|
||||
Each click of the mouse wheel moves _N lines.
|
||||
--wordwrap
|
||||
Wrap lines at spaces.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
LLIINNEE EEDDIITTIINNGG
|
||||
|
||||
These keys can be used to edit text being entered
|
||||
on the "command line" at the bottom of the screen.
|
||||
|
||||
RightArrow ..................... ESC-l ... Move cursor right one character.
|
||||
LeftArrow ...................... ESC-h ... Move cursor left one character.
|
||||
ctrl-RightArrow ESC-RightArrow ESC-w ... Move cursor right one word.
|
||||
ctrl-LeftArrow ESC-LeftArrow ESC-b ... Move cursor left one word.
|
||||
HOME ........................... ESC-0 ... Move cursor to start of line.
|
||||
END ............................ ESC-$ ... Move cursor to end of line.
|
||||
BACKSPACE ................................ Delete char to left of cursor.
|
||||
DELETE ......................... ESC-x ... Delete char under cursor.
|
||||
ctrl-BACKSPACE ESC-BACKSPACE ........... Delete word to left of cursor.
|
||||
ctrl-DELETE .... ESC-DELETE .... ESC-X ... Delete word under cursor.
|
||||
ctrl-U ......... ESC (MS-DOS only) ....... Delete entire line.
|
||||
UpArrow ........................ ESC-k ... Retrieve previous command line.
|
||||
DownArrow ...................... ESC-j ... Retrieve next command line.
|
||||
TAB ...................................... Complete filename & cycle.
|
||||
SHIFT-TAB ...................... ESC-TAB Complete filename & reverse cycle.
|
||||
ctrl-L ................................... Complete filename, list all.
|
||||
@@ -1 +1 @@
|
||||
0.8.10
|
||||
0.8.11
|
||||
@@ -0,0 +1,68 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Common lifecycle surface for host-driven signal primitives.
|
||||
/// Unlike <see cref="AbstractBase"/>, this base does not own indicator inputs,
|
||||
/// historical priming or batch series updates. It publishes position updates;
|
||||
/// predicate and order primitives may define their own typed series bases.
|
||||
/// </summary>
|
||||
public abstract class SignalBase : ISignalPublisher, IDisposable
|
||||
{
|
||||
public int WarmupPeriod { get; protected init; }
|
||||
|
||||
public TPosition Last { get; protected set; }
|
||||
|
||||
public abstract bool IsHot { get; }
|
||||
|
||||
public event TPositionPublishedHandler? Pub;
|
||||
|
||||
protected void PubEvent(TPosition position, bool isNew = true)
|
||||
{
|
||||
Pub?.Invoke(this, new TPositionEventArgs { Position = position, IsNew = isNew });
|
||||
}
|
||||
|
||||
public abstract TPosition Update(TPosition input, bool isNew = true);
|
||||
|
||||
public abstract void Reset();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event arguments for timestamped position updates.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly struct TPositionEventArgs : IEquatable<TPositionEventArgs>
|
||||
{
|
||||
public TPosition Position { get; init; }
|
||||
public bool IsNew { get; init; }
|
||||
|
||||
public bool Equals(TPositionEventArgs other) =>
|
||||
Position.Equals(other.Position) && IsNew == other.IsNew;
|
||||
|
||||
public override bool Equals(object? obj) =>
|
||||
obj is TPositionEventArgs other && Equals(other);
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(Position, IsNew);
|
||||
|
||||
public static bool operator ==(TPositionEventArgs left, TPositionEventArgs right) => left.Equals(right);
|
||||
|
||||
public static bool operator !=(TPositionEventArgs left, TPositionEventArgs right) => !left.Equals(right);
|
||||
}
|
||||
|
||||
public delegate void TPositionPublishedHandler(object? sender, in TPositionEventArgs args);
|
||||
|
||||
public interface ISignalPublisher
|
||||
{
|
||||
event TPositionPublishedHandler? Pub;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class TOrderTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_SetsProperties()
|
||||
{
|
||||
var order = new TOrder(12345, OrderAction.BTO, true);
|
||||
|
||||
Assert.Equal(12345, order.Time);
|
||||
Assert.Equal(OrderAction.BTO, order.Action);
|
||||
Assert.True(order.IsHot);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OrderAction_ContainsExpectedActions()
|
||||
{
|
||||
Assert.Equal(2, (sbyte)OrderAction.BTO);
|
||||
Assert.Equal(1, (sbyte)OrderAction.BTC);
|
||||
Assert.Equal(0, (sbyte)OrderAction.NIL);
|
||||
Assert.Equal(-1, (sbyte)OrderAction.STC);
|
||||
Assert.Equal(-2, (sbyte)OrderAction.STO);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordEquality_UsesAllProperties()
|
||||
{
|
||||
var first = new TOrder(12345, OrderAction.STC, true);
|
||||
var same = new TOrder(12345, OrderAction.STC, true);
|
||||
var different = new TOrder(12345, OrderAction.STO, true);
|
||||
|
||||
Assert.Equal(first, same);
|
||||
Assert.NotEqual(first, different);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Order action represented by a strategy signal. Execution remains host-owned.
|
||||
/// </summary>
|
||||
public enum OrderAction : sbyte
|
||||
{
|
||||
BTO = 2,
|
||||
BTC = 1,
|
||||
NIL = 0,
|
||||
STC = -1,
|
||||
STO = -2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Timestamped order action signal.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly record struct TOrder(long Time, OrderAction Action, bool IsHot);
|
||||
@@ -0,0 +1,33 @@
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class TPositionTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_SetsProperties()
|
||||
{
|
||||
var position = new TPosition(12345, Direction.Long, true);
|
||||
|
||||
Assert.Equal(12345, position.Time);
|
||||
Assert.Equal(Direction.Long, position.Direction);
|
||||
Assert.True(position.IsHot);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Direction_ContainsLongFlatAndShort()
|
||||
{
|
||||
Assert.Equal(-1, (sbyte)Direction.Short);
|
||||
Assert.Equal(0, (sbyte)Direction.Flat);
|
||||
Assert.Equal(1, (sbyte)Direction.Long);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordEquality_UsesAllProperties()
|
||||
{
|
||||
var first = new TPosition(12345, Direction.Flat, true);
|
||||
var same = new TPosition(12345, Direction.Flat, true);
|
||||
var different = new TPosition(12345, Direction.Long, true);
|
||||
|
||||
Assert.Equal(first, same);
|
||||
Assert.NotEqual(first, different);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public enum Direction : sbyte
|
||||
{
|
||||
Short = -1,
|
||||
Flat = 0,
|
||||
Long = 1,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Timestamped long, flat, or short position state.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly record struct TPosition(long Time, Direction Direction, bool IsHot);
|
||||
@@ -0,0 +1,527 @@
|
||||
# Strategy Primitives Specification
|
||||
|
||||
Status: Proposed
|
||||
|
||||
## Purpose
|
||||
|
||||
This directory defines the pluggable signal primitives that sit above QuanTAlib indicators and below a host execution platform such as Quantower or Lean.
|
||||
|
||||
The boundary is **target exposure and trading intent**. These primitives may produce conditions, events, allocations, and protective levels. They must not place orders, simulate fills, model slippage, manage broker connections, or own a backtesting loop.
|
||||
|
||||
The pipeline is:
|
||||
|
||||
```text
|
||||
Transforms / Indicators
|
||||
|
|
||||
v
|
||||
Comparative Predicates
|
||||
|
|
||||
v
|
||||
Temporal Triggers
|
||||
|
|
||||
v
|
||||
Logic Combinators
|
||||
|
|
||||
v
|
||||
Position State Machine ---> StrategyIntent
|
||||
```
|
||||
|
||||
Layer 1 remains in the existing indicator and transform namespaces. This directory owns Layers 2 through 4 and the contracts needed to feed a host-owned Layer 5 position state machine.
|
||||
|
||||
## Repository Baseline and Non-Duplication Rules
|
||||
|
||||
The current library already contains the indicator-side contracts that the signal primitive layer must build on. The signal primitive spec must not duplicate or re-define these behaviors with a different vocabulary.
|
||||
|
||||
Relevant existing abstractions:
|
||||
|
||||
- `lib/core/AbstractBase.cs`: owns the base indicator lifecycle contract (`Name`, `WarmupPeriod`, `IsHot`, `Prime`, `Update`, `Reset`, `Pub`).
|
||||
- `lib/core/BiInputIndicatorBase.cs`: demonstrates the canonical `isNew` correction and rollback pattern for bar updates, including snapshot/restore behaviors.
|
||||
- `lib/core/ringbuffer/RingBuffer.cs`: provides the fixed-capacity, zero-allocation state container pattern for rolling windows and running sums.
|
||||
- `lib/core/tvalue/tvalue.cs`: defines `TValue` as the timestamped streaming value type used throughout the library.
|
||||
- `lib/core/tseries/ITValuePublisher.cs`: defines the event-publishing contract used by indicators to emit value updates.
|
||||
|
||||
The design goal is therefore not to duplicate the indicator lifecycle. Signal primitives will add their own typed outputs and state only where required for predicates, triggers, composition, and host-neutral intent. The lifecycle behavior for those primitives remains a Phase 1 implementation concern.
|
||||
|
||||
## Ecosystem Context
|
||||
|
||||
The design deliberately combines useful ideas from established quantitative ecosystems without importing their unsuitable trade-offs:
|
||||
|
||||
| Ecosystem | Relevant strength | Constraint for QuanTAlib |
|
||||
| :--- | :--- | :--- |
|
||||
| TradingView Pine Script | Mature temporal primitives such as `crossover`, `barssince`, and `valuewhen`. | Series history references are expressive, but rolling buffers are not a zero-allocation streaming model. |
|
||||
| Backtrader and Lean | Operator-based composition, composite indicators, event-driven windows, and reusable indicator graphs. | Their graph and window abstractions must be narrowed to fixed O(1) state for hot-path use here. |
|
||||
| VectorBT | Fast batch signal post-processing such as entry/exit cleaning, first-signal selection, and holding limits. | Its T x N boolean-mask model is batch-only and cannot define the live rollback contract. |
|
||||
| NautilusTrader | Event-driven state nodes backed by a systems-language runtime. | Its event/state separation is a useful model; QuanTAlib keeps the execution boundary outside the library. |
|
||||
|
||||
The target is declarative algebra over streaming components, not a general-purpose backtester.
|
||||
|
||||
## Design Requirements
|
||||
|
||||
Every primitive MUST satisfy these requirements:
|
||||
|
||||
1. Streaming updates use O(1) state per primitive and do not allocate on the hot path.
|
||||
2. `IsHot` propagates recursively through composed components.
|
||||
3. `isNew` updates are deterministic for both confirmed bars and forming-bar ticks.
|
||||
4. A forming-bar update can be rolled back without leaking state into the next bar.
|
||||
5. Components can be composed without a custom strategy loop in user code.
|
||||
6. The output is deterministic for the same input stream and lifecycle sequence.
|
||||
7. Execution remains outside this library.
|
||||
|
||||
## Core Value Types
|
||||
|
||||
The C# API should use small value types for hot-path results:
|
||||
|
||||
```csharp
|
||||
public enum Direction : sbyte
|
||||
{
|
||||
Short = -1,
|
||||
Flat = 0,
|
||||
Long = 1
|
||||
}
|
||||
|
||||
public readonly record struct TPosition(long Time, Direction Direction, bool IsHot);
|
||||
|
||||
public enum OrderAction : sbyte
|
||||
{
|
||||
BTO = 2,
|
||||
BTC = 1,
|
||||
NIL = 0,
|
||||
STC = -1,
|
||||
STO = -2
|
||||
}
|
||||
|
||||
public readonly record struct TOrder(long Time, OrderAction Action, bool IsHot);
|
||||
|
||||
```
|
||||
|
||||
`SizeFactor` is normalized to `[0, 1]`. A host may translate it to quantity, notional, or risk budget. A primitive must not assume account size, leverage, margin, or broker semantics.
|
||||
|
||||
## Lifecycle Contract
|
||||
|
||||
### Confirmed and working state
|
||||
|
||||
Each stateful primitive has two logical snapshots:
|
||||
|
||||
- **Confirmed state**: state at the last completed bar.
|
||||
- **Working state**: state after applying the current forming-bar update.
|
||||
|
||||
For `isNew == false`, update only the working state. Repeated ticks for the same bar replace the working state rather than advancing confirmed history.
|
||||
|
||||
For `isNew == true`:
|
||||
|
||||
1. Promote the previous working state to confirmed state.
|
||||
2. Start the new working state from the promoted confirmed state.
|
||||
3. Apply the new bar value.
|
||||
|
||||
A host may expose an explicit `Commit()` operation if its feed semantics distinguish a final tick from the first tick of the next bar. The implementation must document which convention it uses and test it with repeated intra-bar updates.
|
||||
|
||||
### Priming
|
||||
|
||||
`IsHot` is false until all required input history is available. A composite is hot only when every child required for its current evaluation is hot.
|
||||
|
||||
A strategy state machine MUST remain `Flat` with zero size and no brackets until its complete dependency graph is hot. Warm-up must never produce an entry or exit event.
|
||||
|
||||
### Reset
|
||||
|
||||
Every stateful primitive MUST support reset to its initial, cold state. Reset clears confirmed and working snapshots, previous values, counters, and cached event results.
|
||||
|
||||
## Layer 2: Predicates
|
||||
|
||||
Predicates convert indicator values into boolean states or normalized values. They do not create one-shot events.
|
||||
|
||||
### Required primitives
|
||||
|
||||
| Primitive | Meaning |
|
||||
| :--- | :--- |
|
||||
| `LessThan` | Test whether the left value is less than the right value. The right operand may be a scalar or a streaming value. |
|
||||
| `GreaterThan` | Test whether the left value is greater than the right value. The right operand may be a scalar or a streaming value. |
|
||||
| `Equal` | Test whether two values are equal within an optional epsilon. The default epsilon is the documented library comparison tolerance. |
|
||||
| `InsideChannel` | Test whether a value is inside or outside channel bounds. |
|
||||
| `OutsideChannel` | Test whether a value is above the upper or below the lower bound. |
|
||||
| `ChannelPosition` | Return normalized position within channel bounds. |
|
||||
| `IsRising` | Test whether a value is increasing over the requested observation. |
|
||||
| `IsFalling` | Test whether a value is decreasing over the requested observation. |
|
||||
| `StrictMonotonic` | Require every adjacent observation to move strictly in one direction. |
|
||||
| `QuantileRank` | Return the current value's rank within a fixed lookback window. |
|
||||
| `ZScoreNormalize` | Convert a value into a normalized z-score output. |
|
||||
|
||||
`LessThan`, `GreaterThan`, and `Equal` are the canonical comparison functions. Each accepts either a scalar or a streaming value as its right operand, so separate comparison primitives are unnecessary. The scalar overload must use a specialized allocation-free path and must not create a constant child node on every update.
|
||||
|
||||
The initial API may expose factory methods instead of operators. Operator syntax is a surface goal, not permission to weaken type safety or introduce hidden allocations. Where the type system permits it, `<` maps to `LessThan`, `>` maps to `GreaterThan`, and `==` may map to `Equal` on a library-owned expression type. `<=` and `>=` are not required public predicates; they remain available internally for trigger boundary definitions.
|
||||
|
||||
Example target syntax in C#:
|
||||
|
||||
```csharp
|
||||
var bullish = fast > slow;
|
||||
var oversold = rsi < 30.0;
|
||||
var nearMean = Equal(source, mean, epsilon: 1e-8);
|
||||
var inChannel = InsideChannel(source, lower, upper);
|
||||
```
|
||||
|
||||
Each predicate exposes its current normalized `TValue` through an allocation-free update method. Predicate values are expected to remain in the inclusive range `[0, 1]`; producers must reject or explicitly handle values outside that range rather than silently clamp them. A predicate must not advance a child indicator implicitly; input ownership and update ordering must be explicit. Directional position signals use `TPosition`; order action signals use `TOrder`. A future host-intent layer may add allocation and bracket information.
|
||||
|
||||
Mathematical definitions for the normalized predicates are:
|
||||
|
||||
```text
|
||||
Equal: |A_t - B_t| <= epsilon, where epsilon uses the library default when omitted
|
||||
InsideChannel: Lower_t <= A_t <= Upper_t
|
||||
OutsideChannel: A_t > Upper_t or A_t < Lower_t
|
||||
ChannelPosition: (A_t - Lower_t) / (Upper_t - Lower_t)
|
||||
IsRising: A_t > A_(t-k)
|
||||
IsFalling: A_t < A_(t-k)
|
||||
StrictMonotonic: A_(t-i+1) > A_(t-i), for every i in [1, k]
|
||||
QuantileRank: rank(A_t) / N
|
||||
ZScoreNormalize: (A_t - mean_t) / standard_deviation_t
|
||||
```
|
||||
|
||||
The default epsilon must be a named, documented library constant. It must not be `double.Epsilon`, which is a machine-level spacing value and is generally unsuitable as a financial comparison tolerance. Callers may override it when the scale or precision of the input requires a different tolerance. `Equal` is a value predicate, not C# object identity or structural equality.
|
||||
|
||||
Division by a zero-width channel and a zero-variance z-score must have explicit policies. The default is `IsHot = false` for the normalized result and no event until the denominator becomes valid.
|
||||
|
||||
## Layer 3: Temporal Triggers
|
||||
|
||||
Triggers convert current and prior predicate or value states into one-shot events.
|
||||
|
||||
### Required primitives
|
||||
|
||||
| Primitive | Meaning |
|
||||
| :--- | :--- |
|
||||
| `CrossOver` | Previous left was less than or equal to right; current left is greater. |
|
||||
| `CrossUnder` | Previous left was greater than or equal to right; current left is less. |
|
||||
| `BecameTrue` | Predicate changed from false to true. |
|
||||
| `BecameFalse` | Predicate changed from true to false. |
|
||||
| `BarsSince` | Number of confirmed bars since a predicate was true. |
|
||||
| `ValueWhen` | Capture the latest value when a predicate fires. |
|
||||
| `OccurredWithin` | Test whether an event occurred within a confirmed window. |
|
||||
| `CountOccurrences` | Count event firings over a fixed lookback. |
|
||||
| `HoldFor` | Fire after a predicate remains true for N bars. |
|
||||
| `PivotExtremum` | Confirm a local high or low after the required right-side bars close. |
|
||||
| `DivergenceDetector` | Compare structural price and indicator swings for regular or hidden divergence. |
|
||||
|
||||
Triggers MUST define equality behavior, cold-start behavior, and whether an event can fire during an unconfirmed tick. The default event policy is:
|
||||
|
||||
- Events may be visible while the current bar is forming.
|
||||
- An unconfirmed event must be reversible.
|
||||
- A confirmed event may advance strategy state only through the state machine lifecycle contract.
|
||||
|
||||
A crossover must use a confirmed previous sample and a working current sample. It must not use a previous intra-bar tick as the prior bar value.
|
||||
|
||||
`ValueWhen` must define occurrence numbering (`0` means the most recent event), and `PivotExtremum` must disclose its confirmation delay. A pivot cannot be reported as confirmed until all `right_bars` observations are confirmed; it must never leak future information into a live signal.
|
||||
|
||||
## Layer 4: Logic Combinators
|
||||
|
||||
Combinators compose predicates and triggers while preserving hot-state and rollback semantics.
|
||||
|
||||
### Required primitives
|
||||
|
||||
| Primitive | Meaning |
|
||||
| :--- | :--- |
|
||||
| `All` / `And` | Every child is true. |
|
||||
| `Any` / `Or` | At least one child is true. |
|
||||
| `KOfN` | At least K of N children are true. |
|
||||
| `RegimeFork` | Select a branch according to a regime predicate. |
|
||||
| `Inhibit` | Suppress a trigger while a guard is true. |
|
||||
| `Debounce` | Prevent repeated events during a cooldown window. |
|
||||
| `FirstSignalOnly` | Emit the first entry event and suppress later entries until an exit resets the gate. |
|
||||
| `PriorityCascade` | Select the first eligible event by declared priority. |
|
||||
|
||||
`&`, `|`, and `!` may be provided for compatible C# predicate types. Trigger composition must be explicit where boolean algebra would hide event semantics. For example, `trigger & filter` means the trigger fires only when the filter is true; it does not turn the trigger into a persistent state.
|
||||
|
||||
Combinators MUST:
|
||||
|
||||
- Short-circuit only when doing so cannot change child lifecycle state.
|
||||
- Evaluate child updates in a deterministic declaration order.
|
||||
- Report `IsHot` as the conjunction of required child readiness.
|
||||
- Snapshot internal counters and cooldowns for forming-bar rollback.
|
||||
|
||||
`RegimeFork` routes intent rather than merely combining booleans. For example, an `ADX > 25` regime may select a momentum branch while the alternate branch handles range conditions. `PriorityCascade` is evaluated in declaration order so risk overrides, such as a volatility shock stop, mask lower-priority profit-taking rules.
|
||||
|
||||
The boolean algebra target is:
|
||||
|
||||
```csharp
|
||||
var entry = CrossOver(fast, slow) & (rsi < 30.0) & volumeAboveAverage;
|
||||
var cleanEntry = FirstSignalOnly(entry, exit);
|
||||
var protectedEntry = Inhibit(cleanEntry, newsGuard);
|
||||
```
|
||||
|
||||
Python adapters should expose equivalent factories and operator overloads where Python's operand types make the result unambiguous.
|
||||
|
||||
## O(1) State Models
|
||||
|
||||
The following state budgets are normative for the first implementation:
|
||||
|
||||
| Primitive family | Required state |
|
||||
| :--- | :--- |
|
||||
| `LessThan`, `GreaterThan`, and `Equal` predicates | No history beyond child values. |
|
||||
| `CrossOver`, `CrossUnder`, `BecameTrue`, `BecameFalse` | Previous confirmed sample plus current working sample. |
|
||||
| `BarsSince`, `OccurredWithin`, `HoldFor` | One fixed-width bar counter and one hot flag. |
|
||||
| `ValueWhen` | One latched value, presence flag, and event occurrence state. |
|
||||
| `CountOccurrences` | Fixed-size ring buffer and count; the lookback is fixed at construction. |
|
||||
| `PivotExtremum` | Ring buffer of `left_bars + right_bars + 1` values. |
|
||||
| `DivergenceDetector` | Fixed-size swing registers and the configured lookback state. |
|
||||
| `All`, `Any`, `KOfN` | Immutable child references plus scalar aggregate counters. |
|
||||
| `Debounce` | One cooldown counter and one confirmed/working event state. |
|
||||
| `FirstSignalOnly` | One gate state reset by the configured exit event. |
|
||||
|
||||
No primitive may grow a history collection in response to input. A ring buffer is allowed only when its capacity is fixed during construction and its storage is owned by the component. Batch-only conveniences such as VectorBT-style masks belong in adapters, not in the streaming core.
|
||||
|
||||
## Host-Owned Position State Machine
|
||||
|
||||
A future host-neutral state machine may consume Layer 3 and Layer 4 outputs and emit a host-facing intent. It must not execute orders.
|
||||
|
||||
The state machine owns only logical position state:
|
||||
|
||||
- `Flat`, `Long`, or `Short`.
|
||||
- Entry reference price or host-provided reference.
|
||||
- Allocation or conviction factor.
|
||||
- Stop-loss and take-profit intent.
|
||||
- Confirmed and working snapshots for rollback.
|
||||
|
||||
Before priming, it emits a flat, zero-size intent with no brackets:
|
||||
|
||||
```csharp
|
||||
Direction.Flat, 0.0, null, null
|
||||
```
|
||||
|
||||
The host owns order reconciliation, fills, partial fills, rejected orders, realized position, slippage, commissions, and broker communication. The state machine must accept host position feedback rather than assuming every intent was filled.
|
||||
|
||||
## C# and Python Surface
|
||||
|
||||
C# is the reference implementation for zero-allocation streaming behavior. Python should expose the same conceptual graph for batch and streaming users:
|
||||
|
||||
```python
|
||||
entry = crossover(fast, slow) & (rsi < 30.0)
|
||||
exit = crossunder(fast, slow)
|
||||
strategy = strategy_pipeline(entry_long=entry, exit_long=exit, risk_stop=atr_stop)
|
||||
intent = strategy.update(bar, is_new=True)
|
||||
```
|
||||
|
||||
Python adapters may use native extensions or Python objects at the boundary, but the native streaming core must retain O(1) state and avoid per-update heap allocation. Operator overloads should preserve the same semantics as the C# surface and must not silently evaluate indicators twice.
|
||||
|
||||
## Allocation and Performance Rules
|
||||
|
||||
- No LINQ, closures, boxing, or per-update collection creation in native hot paths.
|
||||
- Child components are wired during construction, not discovered during updates.
|
||||
- Composite child storage is immutable after construction.
|
||||
- Counters use fixed-width integer fields with documented overflow behavior.
|
||||
- Optional values use value types or explicit presence flags in hot paths.
|
||||
- Diagnostics and tracing are opt-in and must not affect signal semantics.
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
Every primitive requires tests for:
|
||||
|
||||
1. Cold, warming, hot, and reset states.
|
||||
2. Exact equality at threshold and crossover boundaries.
|
||||
3. Repeated unconfirmed ticks that oscillate around a boundary.
|
||||
4. Rollback after an intra-bar trigger that is absent at bar close.
|
||||
5. Confirmed event behavior across the next bar.
|
||||
6. Composite short-circuit and evaluation ordering.
|
||||
7. Zero allocation after construction for representative update loops.
|
||||
8. C# and Python parity for the same deterministic input stream.
|
||||
|
||||
Property-based tests should cover arbitrary tick sequences within a bar and compare a rollback-enabled implementation with a reference model that recomputes the current bar from confirmed state.
|
||||
|
||||
## Phased Implementation Plan
|
||||
|
||||
The implementation should proceed as small, independently verifiable increments. Each phase produces a usable capability and has an explicit exit gate. No phase may introduce order execution, fill simulation, slippage, broker communication, or a general-purpose backtesting loop.
|
||||
|
||||
### Phase 0: API and Boundary Review
|
||||
|
||||
**Goal:** Freeze the vocabulary and ownership boundaries before adding code.
|
||||
|
||||
**Status:** Complete as an API and boundary decision record. No signal primitive implementation is included in Phase 0.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- Signal primitives belong under `QuanTAlib.Signals`; indicator and transform implementations remain in their existing namespaces under `lib/*`.
|
||||
- Primitives reuse the established indicator vocabulary: `IsHot`, `WarmupPeriod`, `Reset`, `Update`, and `isNew`. They do not inherit `AbstractBase` merely to gain indicator behavior, and they do not advance child indicators implicitly.
|
||||
- The host updates indicators first; primitives then consume their current values. A primitive's update contract must make input ownership and update ordering explicit.
|
||||
- `LessThan`, `GreaterThan`, and `Equal` are the canonical comparison predicates. Scalar and streaming right operands use the same semantics; `<` and `>` are optional operator facades on library-owned expression types.
|
||||
- `Equal` accepts an optional epsilon and uses a documented library default when omitted. `<=` and `>=` remain internal boundary relations for crossover definitions rather than public predicate types.
|
||||
- Python adapters use the same names and semantics (`less_than`, `greater_than`, `equal`, `is_new`, `is_hot`, and `reset`) without introducing a second execution or state model.
|
||||
|
||||
**Exit gate:** API review confirms that every proposed type has one owner, one update contract, no execution responsibility, and no duplicate lifecycle semantics versus the existing indicator infrastructure.
|
||||
|
||||
### Phase 1: Lifecycle Kernel
|
||||
|
||||
**Goal:** Establish deterministic hot/working/confirmed state behavior using the library's established lifecycle pattern.
|
||||
|
||||
**Repository baseline:** the indicator lifecycle exists in `AbstractBase`, with concrete rollback behavior demonstrated by `BiInputIndicatorBase` and `RingBuffer`. A signal-specific lifecycle kernel does not yet exist and must be designed in Phase 1 without duplicating indicator responsibilities.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- Reuse and clarify the internal lifecycle contract with `IsHot`, `Reset`, confirmed state, and working state.
|
||||
- Snapshot helpers for scalar values, counters, optional values, and event flags, following the same patterns already used in `BiInputIndicatorBase` and `RingBuffer`.
|
||||
- Explicit behavior for `isNew == true` and `isNew == false` updates that matches the existing `AbstractBase` and ring-buffer rollback conventions.
|
||||
- Cold-start behavior and warm-up propagation through a component graph, with no entry or exit intent before the full dependency graph is hot.
|
||||
- Allocation and mutation benchmarks for an empty lifecycle node, measured against the current hot-path conventions of `TValue`, `RingBuffer`, and the existing indicator implementations.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- Repeated forming-bar updates replace working state without mutating confirmed history.
|
||||
- New-bar updates promote working state exactly once and preserve the prior confirmed snapshot.
|
||||
- Reset returns all state to cold.
|
||||
- A cold graph cannot emit a signal or non-flat intent.
|
||||
- A comparison against the existing indicator lifecycle tests confirms the signal kernel does not duplicate indicator behavior.
|
||||
|
||||
**Exit gate:** Lifecycle tests pass across repeated tick sequences, the kernel remains compatible with the existing `AbstractBase`/`RingBuffer` conventions, and there is no duplicate state machine competing with the repository's current lifecycle model.
|
||||
|
||||
### Phase 2: Core Predicates
|
||||
|
||||
**Goal:** Implement allocation-free continuous states and normalized metrics.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- `LessThan` and `GreaterThan` with scalar and streaming right-operand overloads.
|
||||
- `Equal` with an optional non-negative epsilon and a documented default.
|
||||
- `InsideChannel`, `OutsideChannel`, and `ChannelPosition` with zero-width policy.
|
||||
- `IsRising`, `IsFalling`, and `StrictMonotonic` using fixed history state.
|
||||
- `ZScoreNormalize` using a numerically stable fixed-state accumulator.
|
||||
- `QuantileRank` only when its fixed-capacity storage and update policy are defined.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- Boundary equality, NaN/infinite inputs, cold values, and zero denominators.
|
||||
- Predicate parity against straightforward reference calculations.
|
||||
- No child indicator is updated implicitly.
|
||||
|
||||
**Exit gate:** Core predicates are deterministic, hot-state aware, and allocation-free in representative streaming loops.
|
||||
|
||||
### Phase 3: Basic Temporal Triggers
|
||||
|
||||
**Goal:** Convert continuous states into reversible one-shot events.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- `CrossOver` and `CrossUnder` with confirmed previous samples.
|
||||
- `BecameTrue` and `BecameFalse`.
|
||||
- Event result type carrying `Value`, `IsHot`, and event/confirmation status if required by the host.
|
||||
- Forming-bar rollback for every edge detector.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- Equality before a cross and equality on the current sample.
|
||||
- Cross, uncross, recross, and repeated intra-bar oscillation.
|
||||
- No event during warm-up.
|
||||
- A forming-bar event disappears when the bar closes without the event.
|
||||
|
||||
**Exit gate:** The same input stream produces identical results under scalar replay and tick-by-tick updates.
|
||||
|
||||
### Phase 4: Temporal Memory and Structural Events
|
||||
|
||||
**Goal:** Support event sequencing and delayed structural confirmation.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- `BarsSince`, `OccurredWithin`, `CountOccurrences`, and `HoldFor`.
|
||||
- `ValueWhen` with occurrence indexing and presence state.
|
||||
- `PivotExtremum` with explicit right-bar confirmation delay.
|
||||
- `DivergenceDetector` only after swing representation and lookback memory are specified.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- Counter behavior on event, non-event, reset, and overflow boundaries.
|
||||
- Value latching on the exact event bar.
|
||||
- Pivot confirmation never uses unconfirmed future data.
|
||||
- Structural triggers roll back pending candidates correctly.
|
||||
|
||||
**Exit gate:** Every memory primitive has a fixed state budget, documented confirmation timing, and rollback coverage.
|
||||
|
||||
### Phase 5: Boolean Gates and Signal Hygiene
|
||||
|
||||
**Goal:** Compose conditions and events without semantic ambiguity.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- `All` / `And`, `Any` / `Or`, and `KOfN`.
|
||||
- `Inhibit` and `Debounce`.
|
||||
- `FirstSignalOnly` with an exit-controlled reset.
|
||||
- Deterministic child ordering and lifecycle propagation.
|
||||
- Operator syntax where the type system can preserve predicate-versus-trigger meaning.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- Empty and singleton composites, invalid K values, and short-circuit behavior.
|
||||
- Child evaluation order and no duplicate child updates.
|
||||
- Cooldown rollback and first-entry gate rollback.
|
||||
- Composite hot-state behavior with mixed warm-up periods.
|
||||
|
||||
**Exit gate:** Compound graphs behave identically to a reference evaluator and remain zero-allocation after construction.
|
||||
|
||||
### Phase 6: Regime Routing and Priority
|
||||
|
||||
**Goal:** Add contextual branch selection and conflict resolution.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- `RegimeFork` for selecting one active branch.
|
||||
- `PriorityCascade` for ordered risk and signal overrides.
|
||||
- Explicit behavior when multiple branches are hot, cold, or simultaneously eligible.
|
||||
- Diagnostics that are opt-in and do not mutate signal state.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- Regime transitions on confirmed and forming bars.
|
||||
- Branch state isolation and reset behavior.
|
||||
- Priority masking and deterministic tie handling.
|
||||
- No evaluation of inactive branches when lifecycle semantics permit skipping.
|
||||
|
||||
**Exit gate:** Regime and priority behavior is deterministic under replay and does not create hidden execution semantics.
|
||||
|
||||
### Phase 7: Strategy Intent Boundary
|
||||
|
||||
**Goal:** Produce host-consumable target exposure without placing trades.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- Host-neutral `Direction` and host-intent output.
|
||||
- A position state machine for `Flat`, `Long`, and `Short` transitions.
|
||||
- Priming gate that emits flat, zero-size intent until the full graph is hot.
|
||||
- Pluggable stop and take-profit intent providers, including ATR-based examples.
|
||||
- Host position feedback contract for fills, partial fills, rejects, and external position changes.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- Entry and exit transitions, reversal policy, and repeated identical intents.
|
||||
- Intra-bar entry rollback and confirmed-bar promotion.
|
||||
- Bracket recalculation without execution side effects.
|
||||
- Intent stability when host-reported position differs from requested intent.
|
||||
|
||||
**Exit gate:** The state machine emits only deterministic intent values and has no dependency on a broker, order, fill, or account API.
|
||||
|
||||
### Phase 8: Python Parity
|
||||
|
||||
**Goal:** Expose the same semantics to Python users without weakening the streaming core.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- Python factories and operators for the supported primitive subset.
|
||||
- Consistent naming, hot-state, reset, and `is_new` semantics.
|
||||
- Native-backed streaming adapter where performance requires it.
|
||||
- Batch adapter that reuses the same reference semantics rather than defining a second behavior.
|
||||
|
||||
**Tests:**
|
||||
|
||||
- C# and Python golden-stream parity.
|
||||
- Same results for bar-only and forming-tick sequences.
|
||||
- Python operator precedence and invalid-composition errors.
|
||||
- Allocation and throughput benchmarks for native and adapter paths.
|
||||
|
||||
**Exit gate:** Cross-language parity tests pass for all released primitives and differences are documented where language syntax requires them.
|
||||
|
||||
### Phase 9: Hardening and Release Readiness
|
||||
|
||||
**Goal:** Make the primitive layer safe to evolve and suitable for production hosts.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- Full property-based tests for arbitrary intra-bar tick sequences.
|
||||
- Allocation regression tests and benchmark baselines.
|
||||
- Documentation examples for Quantower and Lean-style hosts.
|
||||
- Versioning and compatibility notes for public interfaces and operator behavior.
|
||||
- Review of analyzer, security, NativeAOT, and multi-target build behavior.
|
||||
|
||||
**Exit gate:** Full solution validation passes, performance budgets are recorded, and the public API has documented compatibility guarantees.
|
||||
|
||||
Stateful signal primitives should not proceed beyond their API scaffolding until the Phase 1 lifecycle tests are complete. This staged approach keeps the primitive layer composable without turning QuanTAlib into an execution engine or bloated backtester.
|
||||
@@ -11,6 +11,12 @@ namespace QuanTAlib;
|
||||
/// Combines 2-pole IIR core with trimmed-mean volatility estimation.
|
||||
///
|
||||
/// Key features: phase control [-100,100], adaptive band tracking, dynamic exponent.
|
||||
///
|
||||
/// The 128-sample volatility window uses Index-Linked Sorted Arrays (ILSA): a chronological
|
||||
/// circular buffer plus two integer rank/position maps kept permanently sorted, so each bar
|
||||
/// costs one 7-step binary search and a single memmove of 4-byte indices instead of a full
|
||||
/// re-sort. The middle-65 trimmed mean is maintained as a running sum updated by deterministic
|
||||
/// boundary-crossing deltas rather than 65 sequential additions.
|
||||
/// </remarks>
|
||||
/// <seealso href="Jma.md">Detailed documentation</seealso>
|
||||
/// <seealso href="jma.pine">Reference Pine Script implementation</seealso>
|
||||
@@ -18,8 +24,17 @@ namespace QuanTAlib;
|
||||
public sealed class Jma : AbstractBase
|
||||
{
|
||||
private const int VolWindowSize = 128; // volatility history length
|
||||
private const int VolIndexMask = VolWindowSize - 1;
|
||||
private const int DevWindowSize = 10; // short SMA length for deviation
|
||||
|
||||
private const int JurikTrimCount = 65; // canonical JMA: middle 65 of 128 samples
|
||||
private const int CoreLo = 32; // ceil((128-65)/2)
|
||||
private const int CoreHi = CoreLo + JurikTrimCount - 1; // 96
|
||||
private const int MinVolSamples = 16; // below this, volatility is passed through
|
||||
|
||||
// Periodic exact re-sum to bound floating-point drift of the incremental core sum.
|
||||
private const int SumRefreshInterval = 1024;
|
||||
|
||||
// Jurik core parameters derived from period/phase
|
||||
private readonly double _phaseParam; // 0.5 .. 2.5
|
||||
private readonly double _logParam; // log(sqrt(L))/log(2) + 2, clamped >= 0
|
||||
@@ -28,16 +43,27 @@ public sealed class Jma : AbstractBase
|
||||
private readonly double _logLengthDivider; // Precomputed log(_lengthDivider) for Exp optimization
|
||||
private readonly double _pExponent; // max(logParam - 2, 0.5)
|
||||
|
||||
// Constants for trimmed mean
|
||||
private const int JurikTrimCount = 65; // canonical JMA: middle 65 of 128 samples
|
||||
|
||||
// Buffers
|
||||
private readonly RingBuffer _devBuffer;
|
||||
private readonly RingBuffer _volBuffer;
|
||||
private readonly TValuePublishedHandler _handler;
|
||||
private readonly ITValuePublisher? _source;
|
||||
private bool _disposed;
|
||||
|
||||
// --- ILSA: three contiguous 128-element arrays (1,536 bytes, L1-resident) ---
|
||||
private readonly double[] _chrono; // C: chronological circular buffer of volatility values
|
||||
private readonly int[] _sortedToC; // S_to_C: sorted rank -> chronological position
|
||||
private readonly int[] _cToSorted; // C_to_S: chronological position -> sorted rank
|
||||
|
||||
private int _volCount;
|
||||
private int _oldestC; // chronological position of the expiring element (valid once full)
|
||||
private double _coreSum;
|
||||
private int _sumTicks;
|
||||
|
||||
// --- Undo journal: restores the ILSA to the pre-update state for isNew=false replays ---
|
||||
private bool _undoValid;
|
||||
private bool _undoWasAppend;
|
||||
private int _undoOldC, _undoOldS, _undoNewS, _undoOldestC, _undoCount, _undoSumTicks;
|
||||
private double _undoOldVal, _undoCoreSum;
|
||||
|
||||
// Streaming state (current + previous snapshot for isNew=false)
|
||||
private State _state;
|
||||
private State _p_state;
|
||||
@@ -113,7 +139,9 @@ public sealed class Jma : AbstractBase
|
||||
Name = $"Jma({period},{phase})";
|
||||
|
||||
_devBuffer = new RingBuffer(DevWindowSize);
|
||||
_volBuffer = new RingBuffer(VolWindowSize);
|
||||
_chrono = GC.AllocateArray<double>(VolWindowSize, pinned: true);
|
||||
_sortedToC = GC.AllocateArray<int>(VolWindowSize, pinned: true);
|
||||
_cToSorted = GC.AllocateArray<int>(VolWindowSize, pinned: true);
|
||||
|
||||
Reset();
|
||||
}
|
||||
@@ -125,16 +153,261 @@ public sealed class Jma : AbstractBase
|
||||
source.Pub += _handler;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Reset()
|
||||
{
|
||||
_state = default;
|
||||
_p_state = default;
|
||||
_devBuffer.Clear();
|
||||
_volBuffer.Clear();
|
||||
_volCount = 0;
|
||||
_oldestC = 0;
|
||||
_coreSum = 0.0;
|
||||
_sumTicks = 0;
|
||||
_undoValid = false;
|
||||
Last = default;
|
||||
}
|
||||
|
||||
#region ILSA volatility window
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private double SortedAt(int rank) => _chrono[_sortedToC[rank]];
|
||||
|
||||
/// <summary>Value at <paramref name="rank"/> of the conceptual 127-element array with rank <paramref name="holeS"/> removed.</summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private double GapAt(int rank, int holeS) => SortedAt(rank < holeS ? rank : rank + 1);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ResyncReverseMap(int fromRank, int toRank)
|
||||
{
|
||||
for (int i = fromRank; i <= toRank; i++)
|
||||
{
|
||||
_cToSorted[_sortedToC[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>First rank in [0,count) whose value exceeds <paramref name="value"/>.</summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int UpperBound(double value, int count)
|
||||
{
|
||||
int lo = 0;
|
||||
int hi = count;
|
||||
while (lo < hi)
|
||||
{
|
||||
int mid = (int)(((uint)lo + (uint)hi) >> 1);
|
||||
if (SortedAt(mid) > value)
|
||||
{
|
||||
hi = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
return lo;
|
||||
}
|
||||
|
||||
/// <summary>Binary search over the 127-element array that logically skips rank <paramref name="holeS"/>. Exactly 7 iterations.</summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int UpperBoundWithHole(double value, int holeS)
|
||||
{
|
||||
int lo = 0;
|
||||
int hi = VolWindowSize - 1;
|
||||
while (lo < hi)
|
||||
{
|
||||
int mid = (int)(((uint)lo + (uint)hi) >> 1);
|
||||
if (GapAt(mid, holeS) > value)
|
||||
{
|
||||
hi = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
return lo;
|
||||
}
|
||||
|
||||
private double RecomputeCoreSum()
|
||||
{
|
||||
double sum = 0.0;
|
||||
for (int i = CoreLo; i <= CoreHi; i++)
|
||||
{
|
||||
sum += SortedAt(i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/// <summary>Pushes one volatility sample and returns the reference volatility (trimmed mean).</summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private double PushVolatility(double value)
|
||||
=> _volCount < VolWindowSize ? AppendVolatility(value) : ReplaceOldestVolatility(value);
|
||||
|
||||
private double AppendVolatility(double value)
|
||||
{
|
||||
int n = _volCount;
|
||||
int newS = UpperBound(value, n);
|
||||
|
||||
_undoWasAppend = true;
|
||||
_undoNewS = newS;
|
||||
_undoCount = n;
|
||||
_undoOldestC = _oldestC;
|
||||
_undoCoreSum = _coreSum;
|
||||
_undoSumTicks = _sumTicks;
|
||||
_undoValid = true;
|
||||
|
||||
if (n > newS)
|
||||
{
|
||||
Array.Copy(_sortedToC, newS, _sortedToC, newS + 1, n - newS);
|
||||
}
|
||||
_sortedToC[newS] = n;
|
||||
_chrono[n] = value;
|
||||
_volCount = n + 1;
|
||||
ResyncReverseMap(newS, n);
|
||||
|
||||
if (_volCount == VolWindowSize)
|
||||
{
|
||||
_oldestC = 0;
|
||||
_sumTicks = 0;
|
||||
_coreSum = RecomputeCoreSum();
|
||||
return _coreSum / JurikTrimCount;
|
||||
}
|
||||
|
||||
return _volCount < MinVolSamples ? value : WarmupTrimmedMean(_volCount);
|
||||
}
|
||||
|
||||
private double ReplaceOldestVolatility(double value)
|
||||
{
|
||||
int oldC = _oldestC;
|
||||
int oldS = _cToSorted[oldC];
|
||||
double oldVal = _chrono[oldC];
|
||||
|
||||
// Deletion delta, evaluated against the current 128-element sorted array.
|
||||
double deltaRemove = 0.0;
|
||||
if (oldS <= CoreHi)
|
||||
{
|
||||
double displaced = oldS < CoreLo ? SortedAt(CoreLo) : oldVal;
|
||||
deltaRemove = SortedAt(CoreHi + 1) - displaced;
|
||||
}
|
||||
|
||||
// Insertion rank, and insertion delta against the 127-element post-deletion array.
|
||||
int newS = UpperBoundWithHole(value, oldS);
|
||||
double deltaInsert = 0.0;
|
||||
if (newS <= CoreHi)
|
||||
{
|
||||
double entering = newS < CoreLo ? GapAt(CoreLo - 1, oldS) : value;
|
||||
deltaInsert = entering - GapAt(CoreHi, oldS);
|
||||
}
|
||||
|
||||
_undoWasAppend = false;
|
||||
_undoOldC = oldC;
|
||||
_undoOldS = oldS;
|
||||
_undoNewS = newS;
|
||||
_undoOldVal = oldVal;
|
||||
_undoOldestC = oldC;
|
||||
_undoCount = _volCount;
|
||||
_undoCoreSum = _coreSum;
|
||||
_undoSumTicks = _sumTicks;
|
||||
_undoValid = true;
|
||||
|
||||
// Single contiguous shift of 4-byte indices closes the deletion gap and opens the insertion slot.
|
||||
if (newS <= oldS)
|
||||
{
|
||||
if (oldS > newS)
|
||||
{
|
||||
Array.Copy(_sortedToC, newS, _sortedToC, newS + 1, oldS - newS);
|
||||
}
|
||||
_sortedToC[newS] = oldC;
|
||||
ResyncReverseMap(newS, oldS);
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(_sortedToC, oldS + 1, _sortedToC, oldS, newS - oldS);
|
||||
_sortedToC[newS] = oldC;
|
||||
ResyncReverseMap(oldS, newS);
|
||||
}
|
||||
|
||||
_chrono[oldC] = value;
|
||||
_oldestC = (oldC + 1) & VolIndexMask;
|
||||
|
||||
_coreSum += deltaRemove + deltaInsert;
|
||||
if (++_sumTicks >= SumRefreshInterval)
|
||||
{
|
||||
_sumTicks = 0;
|
||||
_coreSum = RecomputeCoreSum();
|
||||
}
|
||||
|
||||
return _coreSum / JurikTrimCount;
|
||||
}
|
||||
|
||||
/// <summary>Dynamic trim boundaries used while the 128-sample window is still filling.</summary>
|
||||
private double WarmupTrimmedMean(int count)
|
||||
{
|
||||
int slice = (int)Math.Max(5, Math.Round(count * 0.5));
|
||||
int drop = (count - slice) / 2;
|
||||
int start = drop < 0 ? 0 : drop;
|
||||
int end = drop + slice - 1;
|
||||
if (end >= count)
|
||||
{
|
||||
end = count - 1;
|
||||
}
|
||||
|
||||
double sum = 0.0;
|
||||
for (int i = start; i <= end; i++)
|
||||
{
|
||||
sum += SortedAt(i);
|
||||
}
|
||||
return sum / (end - start + 1);
|
||||
}
|
||||
|
||||
/// <summary>Reverses the most recent ILSA mutation (intrabar replay support).</summary>
|
||||
private void UndoVolatility()
|
||||
{
|
||||
if (!_undoValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_undoWasAppend)
|
||||
{
|
||||
int n = _undoCount;
|
||||
int newS = _undoNewS;
|
||||
if (n > newS)
|
||||
{
|
||||
Array.Copy(_sortedToC, newS + 1, _sortedToC, newS, n - newS);
|
||||
}
|
||||
_volCount = n;
|
||||
ResyncReverseMap(newS, n - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int oldS = _undoOldS;
|
||||
int newS = _undoNewS;
|
||||
int oldC = _undoOldC;
|
||||
if (newS <= oldS)
|
||||
{
|
||||
if (oldS > newS)
|
||||
{
|
||||
Array.Copy(_sortedToC, newS + 1, _sortedToC, newS, oldS - newS);
|
||||
}
|
||||
_sortedToC[oldS] = oldC;
|
||||
ResyncReverseMap(newS, oldS);
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(_sortedToC, oldS, _sortedToC, oldS + 1, newS - oldS);
|
||||
_sortedToC[oldS] = oldC;
|
||||
ResyncReverseMap(oldS, newS);
|
||||
}
|
||||
_chrono[oldC] = _undoOldVal;
|
||||
}
|
||||
|
||||
_oldestC = _undoOldestC;
|
||||
_coreSum = _undoCoreSum;
|
||||
_sumTicks = _undoSumTicks;
|
||||
_undoValid = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Core streaming step: feed a single value, get JMA.
|
||||
/// Honors isNew semantics by snapshotting state+buffers.
|
||||
@@ -173,13 +446,13 @@ public sealed class Jma : AbstractBase
|
||||
{
|
||||
_p_state = _state;
|
||||
_devBuffer.Snapshot();
|
||||
_volBuffer.Snapshot();
|
||||
_undoValid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_state = _p_state;
|
||||
_devBuffer.Restore();
|
||||
_volBuffer.Restore();
|
||||
UndoVolatility();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,8 +484,7 @@ public sealed class Jma : AbstractBase
|
||||
double volatility = _devBuffer.Average;
|
||||
|
||||
// 3. 128-bar volatility history + middle-65 trimmed mean
|
||||
_volBuffer.Add(volatility);
|
||||
double refVolatility = CalculateTrimmedMean(volatility);
|
||||
double refVolatility = PushVolatility(volatility);
|
||||
refVolatility = refVolatility <= 0.0 ? deviation : refVolatility;
|
||||
|
||||
// 4. Jurik dynamic exponent d from abs/refVolatility
|
||||
@@ -324,7 +596,7 @@ public sealed class Jma : AbstractBase
|
||||
// so subsequent streaming Update calls with isNew=false will use correct _p_state
|
||||
_p_state = _state;
|
||||
_devBuffer.Snapshot();
|
||||
_volBuffer.Snapshot();
|
||||
_undoValid = false;
|
||||
|
||||
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
|
||||
return new TSeries(t, v);
|
||||
@@ -390,51 +662,4 @@ public sealed class Jma : AbstractBase
|
||||
TSeries results = indicator.Update(source);
|
||||
return (results, indicator);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private double CalculateTrimmedMean(double fallback)
|
||||
{
|
||||
int count = _volBuffer.Count;
|
||||
if (count < 16)
|
||||
{
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// Stack-allocate scratch buffer for sorting (max 128 * 8 bytes = 1KB)
|
||||
// This eliminates the heap-allocated _sorted field and improves cache locality
|
||||
Span<double> sorted = stackalloc double[count];
|
||||
_volBuffer.CopyTo(sorted);
|
||||
sorted.Sort();
|
||||
|
||||
int start, end;
|
||||
if (count >= VolWindowSize)
|
||||
{
|
||||
// canonical JMA: central 65 of 128 -> indices 32..96
|
||||
// Approximately removes the outer 25% on each tail
|
||||
int leftSkip = (int)Math.Ceiling((VolWindowSize - JurikTrimCount) / 2.0);
|
||||
start = leftSkip;
|
||||
end = start + JurikTrimCount - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// for shorter history, use central ~50% as a reasonable proxy
|
||||
int slice = (int)Math.Max(5, Math.Round(count * 0.5));
|
||||
int drop = (count - slice) / 2;
|
||||
start = drop;
|
||||
end = drop + slice - 1;
|
||||
}
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (end >= count)
|
||||
{
|
||||
end = count - 1;
|
||||
}
|
||||
|
||||
int len = end - start + 1;
|
||||
return sorted.Slice(start, len).SumSIMD() / len;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,11 @@ indicator("Jurik Moving Average", "JMA", overlay=true)
|
||||
//@param period Number of bars used in the calculation (>= 1)
|
||||
//@param phase Phase shift (-100 to 100). Negative = smoother, positive = more leading
|
||||
//@returns JMA value with Jurik-style spectral volatility adaptation
|
||||
//
|
||||
// The 128-bar volatility distribution is held permanently sorted and mutated by one
|
||||
// binary-searched remove + insert per bar, and the middle-65 trimmed mean is carried as a
|
||||
// running sum updated by boundary-crossing deltas. This replaces the per-bar rebuild,
|
||||
// array.sort() and 65-element summation of the naive formulation.
|
||||
jma(series float source, simple int period, simple int phase = 0) =>
|
||||
// ---- Precomputed length/phase parameters (constant per series) ----
|
||||
simple float _PHASE = phase < -100 ? 0.5 : phase > 100 ? 2.5 : (phase * 0.01) + 1.5
|
||||
@@ -19,6 +24,12 @@ jma(series float source, simple int period, simple int phase = 0) =>
|
||||
simple float _SQRT_DIV = _SQRT_PARAM / (_SQRT_PARAM + 1.0)
|
||||
simple float _P_EXP = math.max(_LOG_PARAM - 2.0, 0.5)
|
||||
|
||||
// Trimmed-mean core: middle 65 of the 128 sorted volatility samples -> ranks 32..96
|
||||
simple int _CORE_LO = 32
|
||||
simple int _CORE_HI = 96
|
||||
simple int _CORE_CNT = 65
|
||||
simple int _REFRESH = 1024 // periodic exact re-sum to bound float drift
|
||||
|
||||
// ---- Internal state (persists across bars) ----
|
||||
var float paramA = na
|
||||
var float paramB = na
|
||||
@@ -34,11 +45,14 @@ jma(series float source, simple int period, simple int phase = 0) =>
|
||||
var int volCount = 0
|
||||
var array<float> volWindow = array.new_float(10, 0.0)
|
||||
|
||||
// 128-bar volatility distribution
|
||||
var int distIndex = 0
|
||||
// 128-bar volatility distribution, held as a permanently sorted array plus a
|
||||
// chronological circular buffer that only identifies the expiring sample.
|
||||
var array<float> chrono = array.new_float(128, 0.0)
|
||||
var array<float> sortedArr = array.new_float(0)
|
||||
var int chronoIdx = 0
|
||||
var int distCount = 0
|
||||
var array<float> distWindow = array.new_float(128, 0.0)
|
||||
var array<float> sorted = array.new_float(0)
|
||||
var float coreSum = 0.0
|
||||
var int refreshTick = 0
|
||||
|
||||
float current_jma = na
|
||||
|
||||
@@ -75,44 +89,89 @@ jma(series float source, simple int period, simple int phase = 0) =>
|
||||
float highD = volCount > 0 ? cycleDelta / (volCount < 10 ? volCount : 10) : dLocal
|
||||
|
||||
// 3) 128-bar volatility distribution + trimmed mean
|
||||
array.set(distWindow, distIndex, highD)
|
||||
distIndex += 1
|
||||
if distIndex >= 128
|
||||
distIndex := 0
|
||||
float dRef = highD
|
||||
|
||||
if distCount < 128
|
||||
// Warmup: insert in order; trim boundaries are still expanding every bar.
|
||||
int wLo = 0
|
||||
int wHi = distCount
|
||||
while wLo < wHi
|
||||
int wMid = int((wLo + wHi) / 2)
|
||||
if array.get(sortedArr, wMid) > highD
|
||||
wHi := wMid
|
||||
else
|
||||
wLo := wMid + 1
|
||||
array.insert(sortedArr, wLo, highD)
|
||||
array.set(chrono, chronoIdx, highD)
|
||||
chronoIdx := (chronoIdx + 1) % 128
|
||||
distCount += 1
|
||||
|
||||
float dRef = highD
|
||||
if distCount >= 16
|
||||
int count = distCount
|
||||
array.clear(sorted)
|
||||
for i = 0 to count - 1
|
||||
int idx = distIndex - 1 - i
|
||||
if idx < 0
|
||||
idx += 128
|
||||
array.push(sorted, array.get(distWindow, idx))
|
||||
array.sort(sorted)
|
||||
|
||||
int idxLo = 0
|
||||
int idxHi = 0
|
||||
if count >= 128
|
||||
idxLo := 32
|
||||
idxHi := 96
|
||||
else
|
||||
int slice = int(math.max(5.0, math.round(count * 0.5)))
|
||||
int drop = (count - slice) / 2
|
||||
idxLo := drop
|
||||
idxHi := drop + slice - 1
|
||||
|
||||
if idxLo < 0
|
||||
idxLo := 0
|
||||
if idxHi >= count
|
||||
idxHi := count - 1
|
||||
|
||||
float sum = 0.0
|
||||
if distCount == 128
|
||||
float sSeed = 0.0
|
||||
for i = _CORE_LO to _CORE_HI
|
||||
sSeed += array.get(sortedArr, i)
|
||||
coreSum := sSeed
|
||||
refreshTick := 0
|
||||
dRef := coreSum / float(_CORE_CNT)
|
||||
else if distCount >= 16
|
||||
int slice = int(math.max(5.0, math.round(distCount * 0.5)))
|
||||
int drop = (distCount - slice) / 2
|
||||
int idxLo = math.max(drop, 0)
|
||||
int idxHi = math.min(drop + slice - 1, distCount - 1)
|
||||
float sWarm = 0.0
|
||||
for i = idxLo to idxHi
|
||||
sum += array.get(sorted, i)
|
||||
dRef := sum / float(idxHi - idxLo + 1)
|
||||
sWarm += array.get(sortedArr, i)
|
||||
dRef := sWarm / float(idxHi - idxLo + 1)
|
||||
else
|
||||
// Steady state: one delete + one insert, O(1) core-sum update.
|
||||
float oldVal = array.get(chrono, chronoIdx)
|
||||
|
||||
// Leftmost rank holding oldVal (any equal element yields the same multiset).
|
||||
int rLo = 0
|
||||
int rHi = 128
|
||||
while rLo < rHi
|
||||
int rMid = int((rLo + rHi) / 2)
|
||||
if array.get(sortedArr, rMid) < oldVal
|
||||
rLo := rMid + 1
|
||||
else
|
||||
rHi := rMid
|
||||
|
||||
// Deletion delta against the current 128-element sorted array.
|
||||
float dRem = 0.0
|
||||
if rLo <= _CORE_HI
|
||||
float displaced = rLo < _CORE_LO ? array.get(sortedArr, _CORE_LO) : oldVal
|
||||
dRem := array.get(sortedArr, _CORE_HI + 1) - displaced
|
||||
array.remove(sortedArr, rLo)
|
||||
|
||||
// Insertion rank in the 127-element post-deletion array.
|
||||
int iLo = 0
|
||||
int iHi = 127
|
||||
while iLo < iHi
|
||||
int iMid = int((iLo + iHi) / 2)
|
||||
if array.get(sortedArr, iMid) > highD
|
||||
iHi := iMid
|
||||
else
|
||||
iLo := iMid + 1
|
||||
|
||||
// Insertion delta against that same 127-element array.
|
||||
float dIns = 0.0
|
||||
if iLo <= _CORE_HI
|
||||
float entering = iLo < _CORE_LO ? array.get(sortedArr, _CORE_LO - 1) : highD
|
||||
dIns := entering - array.get(sortedArr, _CORE_HI)
|
||||
array.insert(sortedArr, iLo, highD)
|
||||
|
||||
array.set(chrono, chronoIdx, highD)
|
||||
chronoIdx := (chronoIdx + 1) % 128
|
||||
|
||||
coreSum += dRem + dIns
|
||||
refreshTick += 1
|
||||
if refreshTick >= _REFRESH
|
||||
refreshTick := 0
|
||||
float sFix = 0.0
|
||||
for i = _CORE_LO to _CORE_HI
|
||||
sFix += array.get(sortedArr, i)
|
||||
coreSum := sFix
|
||||
dRef := coreSum / float(_CORE_CNT)
|
||||
|
||||
if dRef <= 0.0
|
||||
dRef := dLocal
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v10.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v10.0": {
|
||||
"NDBadge/1.0.0": {
|
||||
"dependencies": {
|
||||
"SkiaSharp": "3.119.1",
|
||||
"SkiaSharp.NativeAssets.Linux": "3.119.1"
|
||||
},
|
||||
"runtime": {
|
||||
"NDBadge.dll": {}
|
||||
}
|
||||
},
|
||||
"SkiaSharp/3.119.1": {
|
||||
"dependencies": {
|
||||
"SkiaSharp.NativeAssets.Win32": "3.119.1",
|
||||
"SkiaSharp.NativeAssets.macOS": "3.119.1"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net8.0/SkiaSharp.dll": {
|
||||
"assemblyVersion": "3.119.0.0",
|
||||
"fileVersion": "3.119.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SkiaSharp.NativeAssets.Linux/3.119.1": {
|
||||
"runtimeTargets": {
|
||||
"runtimes/linux-arm/native/libSkiaSharp.so": {
|
||||
"rid": "linux-arm",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-arm64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-arm64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-loongarch64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-loongarch64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-musl-arm/native/libSkiaSharp.so": {
|
||||
"rid": "linux-musl-arm",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-musl-arm64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-musl-arm64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-musl-loongarch64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-musl-loongarch64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-musl-riscv64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-musl-riscv64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-musl-x64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-musl-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-riscv64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-riscv64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-x64/native/libSkiaSharp.so": {
|
||||
"rid": "linux-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-x86/native/libSkiaSharp.so": {
|
||||
"rid": "linux-x86",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SkiaSharp.NativeAssets.macOS/3.119.1": {
|
||||
"runtimeTargets": {
|
||||
"runtimes/osx/native/libSkiaSharp.dylib": {
|
||||
"rid": "osx",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SkiaSharp.NativeAssets.Win32/3.119.1": {
|
||||
"runtimeTargets": {
|
||||
"runtimes/win-arm64/native/libSkiaSharp.dll": {
|
||||
"rid": "win-arm64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/win-x64/native/libSkiaSharp.dll": {
|
||||
"rid": "win-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/win-x86/native/libSkiaSharp.dll": {
|
||||
"rid": "win-x86",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"NDBadge/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"SkiaSharp/3.119.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-+Ru1BTSZQne3Vp+vbSb50Ke3Nlc3ZnItxx4+751J9WZ8YzLKAV/n+9DAo4zFTyeCI//ueT63c+VybmTTpYBEiw==",
|
||||
"path": "skiasharp/3.119.1",
|
||||
"hashPath": "skiasharp.3.119.1.nupkg.sha512"
|
||||
},
|
||||
"SkiaSharp.NativeAssets.Linux/3.119.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-9YNoc4SeKvQhrwiqwT4ezkNfMywPdPSK+UFvo/CaoXqLixcnYOTsQKm5BF9mc4+q3vKgDtEgMt0d1ygZhJTEHg==",
|
||||
"path": "skiasharp.nativeassets.linux/3.119.1",
|
||||
"hashPath": "skiasharp.nativeassets.linux.3.119.1.nupkg.sha512"
|
||||
},
|
||||
"SkiaSharp.NativeAssets.macOS/3.119.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-6hR3BdLhApjDxR1bFrJ7/lMydPfI01s3K+3WjIXFUlfC0MFCFCwRzv+JtzIkW9bDXs7XUVQS+6EVf0uzCasnGQ==",
|
||||
"path": "skiasharp.nativeassets.macos/3.119.1",
|
||||
"hashPath": "skiasharp.nativeassets.macos.3.119.1.nupkg.sha512"
|
||||
},
|
||||
"SkiaSharp.NativeAssets.Win32/3.119.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-8C4GSXVJqSr0y3Tyyv5jz6MJSTVUyYkMjeKrzK+VyZPGLo89MNoUEclVuYahzOCDdtbfXrd2HtxXfDuvoSXrUw==",
|
||||
"path": "skiasharp.nativeassets.win32/3.119.1",
|
||||
"hashPath": "skiasharp.nativeassets.win32.3.119.1.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net10.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "10.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:xlink='http://www.w3.org/1999/xlink' width='101.38281' height='20' role='img' aria-label='languages: 5'>
|
||||
<title># Classes: 1181</title>
|
||||
<linearGradient id='s' x2='0' y2='100%'>
|
||||
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
||||
<stop offset='1' stop-opacity='.1'/>
|
||||
</linearGradient>
|
||||
<clipPath id='r'>
|
||||
<rect width='101.38281' height='20' rx='3' fill='#fff'/>
|
||||
</clipPath>
|
||||
<g clip-path='url(#r)'>
|
||||
<rect width='62.6875' height='20' fill='#555'/>
|
||||
<rect x='62.6875' width='38.695312' height='20' fill='#007ec6'/>
|
||||
<rect width='101.38281' height='20' fill='url(#s)'/>
|
||||
</g>
|
||||
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
|
||||
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='526.875'># Classes</text>
|
||||
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='526.875'># Classes</text>
|
||||
<text aria-hidden='true' x='666.875' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1181</text>
|
||||
<text x='666.875' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1181</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:xlink='http://www.w3.org/1999/xlink' width='188.0957' height='20' role='img' aria-label='languages: 5'>
|
||||
<title>Percentage of Comments: 33.07</title>
|
||||
<linearGradient id='s' x2='0' y2='100%'>
|
||||
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
||||
<stop offset='1' stop-opacity='.1'/>
|
||||
</linearGradient>
|
||||
<clipPath id='r'>
|
||||
<rect width='188.0957' height='20' rx='3' fill='#fff'/>
|
||||
</clipPath>
|
||||
<g clip-path='url(#r)'>
|
||||
<rect width='146.0664' height='20' fill='#555'/>
|
||||
<rect x='146.0664' width='42.029297' height='20' fill='#007ec6'/>
|
||||
<rect width='188.0957' height='20' fill='url(#s)'/>
|
||||
</g>
|
||||
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
|
||||
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='1360.6641'>Percentage of Comments</text>
|
||||
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='1360.6641'>Percentage of Comments</text>
|
||||
<text aria-hidden='true' x='1500.6641' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='300.29297'>33.07</text>
|
||||
<text x='1500.6641' y='140' transform='scale(.1)' fill='#FFF' textLength='300.29297'>33.07</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:xlink='http://www.w3.org/1999/xlink' width='281.4414' height='20' role='img' aria-label='languages: 5'>
|
||||
<title>Average Cyclomatic Complexity for Methods: 2.13</title>
|
||||
<linearGradient id='s' x2='0' y2='100%'>
|
||||
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
||||
<stop offset='1' stop-opacity='.1'/>
|
||||
</linearGradient>
|
||||
<clipPath id='r'>
|
||||
<rect width='281.4414' height='20' rx='3' fill='#fff'/>
|
||||
</clipPath>
|
||||
<g clip-path='url(#r)'>
|
||||
<rect width='246.08594' height='20' fill='#555'/>
|
||||
<rect x='246.08594' width='35.35547' height='20' fill='#007ec6'/>
|
||||
<rect width='281.4414' height='20' fill='url(#s)'/>
|
||||
</g>
|
||||
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
|
||||
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='2360.8594'>Average Cyclomatic Complexity for Methods</text>
|
||||
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='2360.8594'>Average Cyclomatic Complexity for Methods</text>
|
||||
<text aria-hidden='true' x='2500.8594' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='233.55469'>2.13</text>
|
||||
<text x='2500.8594' y='140' transform='scale(.1)' fill='#FFF' textLength='233.55469'>2.13</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:xlink='http://www.w3.org/1999/xlink' width='125.39453' height='20' role='img' aria-label='languages: 5'>
|
||||
<title># Source Files: 1893</title>
|
||||
<linearGradient id='s' x2='0' y2='100%'>
|
||||
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
||||
<stop offset='1' stop-opacity='.1'/>
|
||||
</linearGradient>
|
||||
<clipPath id='r'>
|
||||
<rect width='125.39453' height='20' rx='3' fill='#fff'/>
|
||||
</clipPath>
|
||||
<g clip-path='url(#r)'>
|
||||
<rect width='86.69922' height='20' fill='#555'/>
|
||||
<rect x='86.69922' width='38.695312' height='20' fill='#007ec6'/>
|
||||
<rect width='125.39453' height='20' fill='url(#s)'/>
|
||||
</g>
|
||||
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
|
||||
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='766.9922'># Source Files</text>
|
||||
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='766.9922'># Source Files</text>
|
||||
<text aria-hidden='true' x='906.9922' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1893</text>
|
||||
<text x='906.9922' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1893</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:xlink='http://www.w3.org/1999/xlink' width='146.10156' height='20' role='img' aria-label='languages: 5'>
|
||||
<title># Lines of Code: 152828</title>
|
||||
<linearGradient id='s' x2='0' y2='100%'>
|
||||
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
||||
<stop offset='1' stop-opacity='.1'/>
|
||||
</linearGradient>
|
||||
<clipPath id='r'>
|
||||
<rect width='146.10156' height='20' rx='3' fill='#fff'/>
|
||||
</clipPath>
|
||||
<g clip-path='url(#r)'>
|
||||
<rect width='94.05859' height='20' fill='#555'/>
|
||||
<rect x='94.05859' width='52.04297' height='20' fill='#007ec6'/>
|
||||
<rect width='146.10156' height='20' fill='url(#s)'/>
|
||||
</g>
|
||||
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
|
||||
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='840.58594'># Lines of Code</text>
|
||||
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='840.58594'># Lines of Code</text>
|
||||
<text aria-hidden='true' x='980.58594' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='400.4297'>152828</text>
|
||||
<text x='980.58594' y='140' transform='scale(.1)' fill='#FFF' textLength='400.4297'>152828</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:xlink='http://www.w3.org/1999/xlink' width='111.40234' height='20' role='img' aria-label='languages: 5'>
|
||||
<title># Methods: 15405</title>
|
||||
<linearGradient id='s' x2='0' y2='100%'>
|
||||
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
||||
<stop offset='1' stop-opacity='.1'/>
|
||||
</linearGradient>
|
||||
<clipPath id='r'>
|
||||
<rect width='111.40234' height='20' rx='3' fill='#fff'/>
|
||||
</clipPath>
|
||||
<g clip-path='url(#r)'>
|
||||
<rect width='66.0332' height='20' fill='#555'/>
|
||||
<rect x='66.0332' width='45.36914' height='20' fill='#007ec6'/>
|
||||
<rect width='111.40234' height='20' fill='url(#s)'/>
|
||||
</g>
|
||||
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
|
||||
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='560.33203'># Methods</text>
|
||||
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='560.33203'># Methods</text>
|
||||
<text aria-hidden='true' x='700.33203' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='333.6914'>15405</text>
|
||||
<text x='700.33203' y='140' transform='scale(.1)' fill='#FFF' textLength='333.6914'>15405</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,22 +0,0 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:xlink='http://www.w3.org/1999/xlink' width='127.39844' height='20' role='img' aria-label='languages: 5'>
|
||||
<title># Public Types: 1222</title>
|
||||
<linearGradient id='s' x2='0' y2='100%'>
|
||||
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
|
||||
<stop offset='1' stop-opacity='.1'/>
|
||||
</linearGradient>
|
||||
<clipPath id='r'>
|
||||
<rect width='127.39844' height='20' rx='3' fill='#fff'/>
|
||||
</clipPath>
|
||||
<g clip-path='url(#r)'>
|
||||
<rect width='88.703125' height='20' fill='#555'/>
|
||||
<rect x='88.703125' width='38.695312' height='20' fill='#007ec6'/>
|
||||
<rect width='127.39844' height='20' fill='url(#s)'/>
|
||||
</g>
|
||||
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
|
||||
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='787.03125'># Public Types</text>
|
||||
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='787.03125'># Public Types</text>
|
||||
<text aria-hidden='true' x='927.03125' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1222</text>
|
||||
<text x='927.03125' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1222</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- NDepend coverage exclusion file -->
|
||||
<RunSettings>
|
||||
<DataCollectionRunSettings>
|
||||
<DataCollectors>
|
||||
<DataCollector friendlyName="Code Coverage">
|
||||
<Configuration>
|
||||
<CodeCoverage>
|
||||
<Functions>
|
||||
<!-- Exclude explicit interface implementations that cause NDepend mismatch warnings -->
|
||||
<Exclude>
|
||||
<Function>.*::System\.Collections\..*\.GetEnumerator\(\).*</Function>
|
||||
</Exclude>
|
||||
</Functions>
|
||||
</CodeCoverage>
|
||||
</Configuration>
|
||||
</DataCollector>
|
||||
</DataCollectors>
|
||||
</DataCollectionRunSettings>
|
||||
</RunSettings>
|
||||
@@ -1,122 +0,0 @@
|
||||
#!/usr/bin/env pwsh
|
||||
#requires -Version 7.0
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generates NDepend metric badges for QuanTAlib
|
||||
.DESCRIPTION
|
||||
Creates SVG badges for key quality metrics that reinforce QuanTAlib's
|
||||
identity: scale, quality, low complexity, and comprehensive documentation.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$NDBadgePath = "$PSScriptRoot\NDBadge.exe",
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$XmlPath = ".\ndepend\NDependOut\TrendMetrics\NDependTrendData2026.xml"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# Validate prerequisites
|
||||
if (-not (Test-Path $NDBadgePath)) {
|
||||
Write-Error "NDBadge.exe not found at: $NDBadgePath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not (Test-Path $XmlPath)) {
|
||||
Write-Error "NDepend trend data XML not found at: $XmlPath"
|
||||
Write-Information "Please run ndepend.ps1 first to generate analysis data"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$ScriptDir = $PSScriptRoot
|
||||
$OutputDir = Join-Path $ScriptDir "badges"
|
||||
|
||||
# Create output directory
|
||||
if (-not (Test-Path $OutputDir)) {
|
||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||
}
|
||||
|
||||
Write-Information "=== Generating QuanTAlib Quality Badges ==="
|
||||
Write-Information "Output directory: $OutputDir`n"
|
||||
|
||||
# Selected badges for QuanTAlib README
|
||||
Write-Information "Generating QuanTAlib badges..."
|
||||
|
||||
$HighValueBadges = @(
|
||||
@{
|
||||
Metric = "# Lines of Code"
|
||||
Output = "loc.svg"
|
||||
Description = "Total lines of code"
|
||||
},
|
||||
@{
|
||||
Metric = "# Source Files"
|
||||
Output = "files.svg"
|
||||
Description = "Source files"
|
||||
},
|
||||
@{
|
||||
Metric = "# Classes"
|
||||
Output = "classes.svg"
|
||||
Description = "Classes"
|
||||
},
|
||||
@{
|
||||
Metric = "# Methods"
|
||||
Output = "methods.svg"
|
||||
Description = "Methods"
|
||||
},
|
||||
@{
|
||||
Metric = "# Public Types"
|
||||
Output = "public-api.svg"
|
||||
Description = "Public API surface"
|
||||
},
|
||||
@{
|
||||
Metric = "Percentage of Comments"
|
||||
Output = "comments.svg"
|
||||
Description = "Comment percentage"
|
||||
},
|
||||
@{
|
||||
Metric = "Average Cyclomatic Complexity for Methods"
|
||||
Output = "complexity.svg"
|
||||
Description = "Average complexity"
|
||||
}
|
||||
)
|
||||
|
||||
foreach ($badge in $HighValueBadges) {
|
||||
$outputPath = Join-Path $OutputDir $badge.Output
|
||||
Write-Information " [$($badge.Output)] $($badge.Description)"
|
||||
|
||||
& $NDBadgePath --xml $XmlPath --metric $badge.Metric --output $outputPath
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warning "Failed to generate badge: $($badge.Output)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Generate summary
|
||||
Write-Information "`n=== Badge Generation Complete ==="
|
||||
$generatedBadges = Get-ChildItem -Path $OutputDir -Filter "*.svg"
|
||||
Write-Information "Generated $($generatedBadges.Count) badges in: $OutputDir"
|
||||
|
||||
Write-Information "`nGenerated badges:"
|
||||
$HighValueBadges | ForEach-Object {
|
||||
Write-Information " - $($_.Output.PadRight(20)) : $($_.Description)"
|
||||
}
|
||||
|
||||
Write-Information "`nMarkdown snippet for README.md:"
|
||||
Write-Information @"
|
||||
|
||||
## Quality Metrics
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
|
||||
"@
|
||||
@@ -1,239 +0,0 @@
|
||||
#!/usr/bin/env pwsh
|
||||
#requires -Version 7.0
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$NdependLicense = $env:NDEPEND_LICENSE
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# Configuration
|
||||
# Determine NDepend installation path based on OS
|
||||
if ($IsWindows -or $env:OS -like "Windows*") {
|
||||
$NdependDll = "C:\ndepend\net10.0\NDepend.Console.MultiOS.dll"
|
||||
} else {
|
||||
$NdependDll = Join-Path $HOME "NDepend/net10.0/NDepend.Console.MultiOS.dll"
|
||||
}
|
||||
# Ensure ScriptDir is set correctly even if $PSScriptRoot is empty (e.g., dot-sourced)
|
||||
$ScriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Path }
|
||||
$ProjectRoot = Split-Path -Parent $ScriptDir
|
||||
$CoverageDir = Join-Path $ScriptDir "coverage"
|
||||
$SarifDir = Join-Path $ProjectRoot ".sarif"
|
||||
$SolutionFile = Join-Path $ProjectRoot "QuanTAlib.slnx"
|
||||
$TestProject = Join-Path $ProjectRoot "lib/QuanTAlib.Tests.csproj"
|
||||
$TestProject2 = Join-Path $ProjectRoot "quantower/Quantower.Tests.csproj"
|
||||
$RunSettingsFile = Join-Path $ProjectRoot ".config/coverage.runsettings"
|
||||
$NdependProject = Join-Path $ScriptDir "quantalib.ndproj"
|
||||
|
||||
# Validate prerequisites
|
||||
if (-not (Test-Path $NdependDll)) {
|
||||
Write-Error "NDepend console not found at: $NdependDll"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($NdependLicense)) {
|
||||
Write-Warning "NDEPEND_LICENSE environment variable not set. License activation may fail."
|
||||
}
|
||||
|
||||
if (-not (Test-Path $SolutionFile)) {
|
||||
Write-Error "Solution file not found: $SolutionFile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Helper function for section headers
|
||||
function Write-Section {
|
||||
param([string]$Message)
|
||||
Write-Information "`n=== $Message ==="
|
||||
}
|
||||
|
||||
# Track analysis failure
|
||||
$AnalysisFailed = $false
|
||||
|
||||
try {
|
||||
# Create .sarif directory
|
||||
Write-Section "Creating .sarif directory for Roslyn analyzer output"
|
||||
if (-not (Test-Path $SarifDir)) {
|
||||
New-Item -ItemType Directory -Path $SarifDir -Force | Out-Null
|
||||
}
|
||||
Write-Information "SARIF directory: $SarifDir"
|
||||
|
||||
# Restore, clean, and build
|
||||
Write-Section "Cleaning and building solution (generates SARIF files)"
|
||||
|
||||
Write-Information "Restoring packages..."
|
||||
dotnet restore $SolutionFile -v q
|
||||
if ($LASTEXITCODE -ne 0) { throw "Restore failed with exit code $LASTEXITCODE" }
|
||||
|
||||
Write-Information "Cleaning solution..."
|
||||
dotnet clean $SolutionFile -v q
|
||||
if ($LASTEXITCODE -ne 0) { throw "Clean failed with exit code $LASTEXITCODE" }
|
||||
|
||||
Write-Information "Removing old coverage data..."
|
||||
if (Test-Path $CoverageDir) {
|
||||
Remove-Item -Path $CoverageDir -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Information "Building solution..."
|
||||
dotnet build $SolutionFile -c Debug --no-incremental
|
||||
if ($LASTEXITCODE -ne 0) { throw "Build failed with exit code $LASTEXITCODE" }
|
||||
|
||||
# Run tests with coverage (QuanTAlib.Tests)
|
||||
Write-Section "Running tests with coverage (QuanTAlib.Tests)"
|
||||
dotnet test $TestProject `
|
||||
-c Debug `
|
||||
--no-build `
|
||||
--collect:"XPlat Code Coverage" `
|
||||
--settings $RunSettingsFile `
|
||||
--results-directory:$CoverageDir
|
||||
|
||||
if ($LASTEXITCODE -ne 0) { throw "Tests failed for QuanTAlib.Tests with exit code $LASTEXITCODE" }
|
||||
|
||||
# Run tests with coverage (Quantower.Tests)
|
||||
Write-Section "Running tests with coverage (Quantower.Tests)"
|
||||
dotnet test $TestProject2 `
|
||||
-c Debug `
|
||||
--no-build `
|
||||
--collect:"XPlat Code Coverage" `
|
||||
--settings $RunSettingsFile `
|
||||
--results-directory:$CoverageDir
|
||||
|
||||
if ($LASTEXITCODE -ne 0) { throw "Tests failed for Quantower.Tests with exit code $LASTEXITCODE" }
|
||||
|
||||
# Find coverage files
|
||||
Write-Information "`nSearching for coverage files..."
|
||||
$CoverageFiles = Get-ChildItem -Path $CoverageDir -Filter "coverage.opencover.xml" -Recurse -File |
|
||||
Select-Object -ExpandProperty FullName
|
||||
|
||||
if (-not $CoverageFiles) {
|
||||
Write-Warning "No coverage files found in $CoverageDir"
|
||||
}
|
||||
else {
|
||||
$CoverageFiles | ForEach-Object {
|
||||
Write-Information "Coverage file: $_"
|
||||
}
|
||||
}
|
||||
|
||||
# Run JetBrains InspectCode
|
||||
Write-Section "Running JetBrains InspectCode"
|
||||
$InspectCodeOutput = Join-Path $SarifDir "resharper.sarif.json"
|
||||
$jbPath = Get-Command "jb" -ErrorAction SilentlyContinue
|
||||
if ($jbPath) {
|
||||
Write-Information "Running InspectCode analysis..."
|
||||
jb inspectcode $SolutionFile --output=$InspectCodeOutput --format=Sarif --no-build
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warning "InspectCode completed with exit code $LASTEXITCODE"
|
||||
}
|
||||
else {
|
||||
Write-Information "InspectCode SARIF saved to: $InspectCodeOutput"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Warning "JetBrains CLI (jb) not found. Skipping InspectCode analysis."
|
||||
Write-Information " Install with: dotnet tool install -g JetBrains.ReSharper.GlobalTools"
|
||||
}
|
||||
|
||||
# List SARIF files
|
||||
Write-Section "SARIF files generated"
|
||||
$SarifFiles = Get-ChildItem -Path $SarifDir -Filter "*.json" -ErrorAction SilentlyContinue
|
||||
if ($SarifFiles) {
|
||||
$SarifFiles | ForEach-Object {
|
||||
Write-Information " $($_.Name) ($([math]::Round($_.Length / 1KB, 2)) KB)"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Information "No SARIF files found"
|
||||
}
|
||||
|
||||
# Activate NDepend license
|
||||
Write-Section "Activating NDepend license"
|
||||
if (-not [string]::IsNullOrWhiteSpace($NdependLicense)) {
|
||||
dotnet $NdependDll --RegLic $NdependLicense
|
||||
if ($LASTEXITCODE -ne 0) { Write-Warning "License activation returned exit code $LASTEXITCODE" }
|
||||
}
|
||||
else {
|
||||
Write-Warning "Skipping license activation (no license provided)"
|
||||
}
|
||||
|
||||
# Run NDepend analysis
|
||||
Write-Section "Running NDepend analysis"
|
||||
$NdependArgs = @($NdependProject)
|
||||
if ($CoverageFiles) {
|
||||
$NdependArgs += "/CoverageFiles"
|
||||
foreach ($file in $CoverageFiles) {
|
||||
$NdependArgs += $file
|
||||
}
|
||||
}
|
||||
|
||||
dotnet $NdependDll @NdependArgs
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warning "NDepend analysis completed with exit code $LASTEXITCODE"
|
||||
$AnalysisFailed = $true
|
||||
}
|
||||
|
||||
}
|
||||
catch {
|
||||
Write-Error "Script failed: $_"
|
||||
$AnalysisFailed = $true
|
||||
}
|
||||
finally {
|
||||
# Always deactivate license
|
||||
Write-Section "Deactivating NDepend license"
|
||||
if (-not [string]::IsNullOrWhiteSpace($NdependLicense)) {
|
||||
dotnet $NdependDll --UnregLic
|
||||
if ($LASTEXITCODE -ne 0) { Write-Warning "License deactivation returned exit code $LASTEXITCODE" }
|
||||
}
|
||||
else {
|
||||
Write-Information "Skipping license deactivation (no license provided)"
|
||||
}
|
||||
|
||||
# Generate badges from NDepend trend data
|
||||
Write-Section "Generating quality badges"
|
||||
$NDBadgePath = Join-Path $ScriptDir "NDBadge.exe"
|
||||
# Find the most recent trend data file
|
||||
$TrendMetricsDir = Join-Path $ScriptDir "NDependOut\TrendMetrics"
|
||||
$TrendXml = if (Test-Path $TrendMetricsDir) {
|
||||
Get-ChildItem -Path $TrendMetricsDir -Filter "NDependTrendData*.xml" -File |
|
||||
Sort-Object Name -Descending |
|
||||
Select-Object -First 1 -ExpandProperty FullName
|
||||
}
|
||||
else { $null }
|
||||
$BadgeDir = Join-Path $ScriptDir "badges"
|
||||
|
||||
if ((Test-Path $NDBadgePath) -and $TrendXml -and (Test-Path $TrendXml)) {
|
||||
if (-not (Test-Path $BadgeDir)) {
|
||||
New-Item -ItemType Directory -Path $BadgeDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$Badges = @(
|
||||
@{ Metric = "# Lines of Code"; Output = "loc.svg" },
|
||||
@{ Metric = "# Source Files"; Output = "files.svg" },
|
||||
@{ Metric = "# Classes"; Output = "classes.svg" },
|
||||
@{ Metric = "# Methods"; Output = "methods.svg" },
|
||||
@{ Metric = "# Public Types"; Output = "public-api.svg" },
|
||||
@{ Metric = "Percentage of Comments"; Output = "comments.svg" },
|
||||
@{ Metric = "Average Cyclomatic Complexity for Methods"; Output = "complexity.svg" }
|
||||
)
|
||||
|
||||
foreach ($badge in $Badges) {
|
||||
$outputPath = Join-Path $BadgeDir $badge.Output
|
||||
& $NDBadgePath --xml $TrendXml --metric $badge.Metric --output $outputPath 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Information " Generated: $($badge.Output)"
|
||||
}
|
||||
}
|
||||
Write-Information "Badges saved to: $BadgeDir"
|
||||
}
|
||||
else {
|
||||
Write-Information "Skipping badge generation (NDBadge.exe or trend data not found)"
|
||||
}
|
||||
|
||||
Write-Section "Done"
|
||||
|
||||
if ($AnalysisFailed) {
|
||||
Write-Information "Note: Analysis completed with quality gate failures"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
@@ -1,565 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<NDepend AppName="quantalib" Platform="DotNet" FileWrittenByProductVersion="2026.1.2.9787">
|
||||
<OutputDir KeepXmlFiles="True">.\NDependOut</OutputDir>
|
||||
<IDEFiles>
|
||||
<IDEFile FilePath="..\QuanTAlib.slnx" Filters="-test" Configuration="DEBUG|AnyCPU">
|
||||
<RootDirResolvingInfo Enabled="False" Hints="Debug|bin|.bin|b|AnyCPU|x64|x86|v*.*|net*" TimeOut="10">
|
||||
<RootDir>.</RootDir>
|
||||
</RootDirResolvingInfo>
|
||||
</IDEFile>
|
||||
</IDEFiles>
|
||||
<RuntimeProfileDesc>.NET 10.0</RuntimeProfileDesc>
|
||||
<Assemblies />
|
||||
<Dirs />
|
||||
<MergeCodeGeneratedByCompiler>True</MergeCodeGeneratedByCompiler>
|
||||
<CompressNDar>True</CompressNDar>
|
||||
<ZipSourceFiles>True</ZipSourceFiles>
|
||||
<ForceReturnZeroExitCode>False</ForceReturnZeroExitCode>
|
||||
<Report Kind="0" SectionsEnabled="110591" XslPath="" DefaultTheme="dark" Flags="4455424" NbItemsToUnfold="3" NbItemsPerRule="20" MaxNbSourceFiles="2000" />
|
||||
<BuildComparisonSetting ProjectMode="CurrentProject" BuildMode="NDaysAgoAnalysisResult" ProjectFileToCompareWith="" BuildFileToCompareWith="" NDaysAgo="30" />
|
||||
<BaselineInUISetting ProjectMode="CurrentProject" BuildMode="NDaysAgoAnalysisResult" ProjectFileToCompareWith="" BuildFileToCompareWith="" NDaysAgo="30" />
|
||||
<CoverageFiles CoverageDir="" CoverageDirFilter="" UncoverableAttribute="" CoverageExclusionFile="">
|
||||
<CoverageFile>.\coverage\43fa2c87-f47e-4cfd-bc4d-2b640a2a37d6\coverage.opencover.xml</CoverageFile>
|
||||
</CoverageFiles>
|
||||
<TrendMetrics UseCustomLog="False" LogRecurrence="3" LogLabel="2" UseCustomDir="False" CustomDir="">
|
||||
<Chart Name="Size" ShowInReport="True">
|
||||
<Serie MetricName="# Lines of Code" MetricUnit="Loc" Color="#FF00BFFF" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="# Lines of Code Covered" MetricUnit="Loc" Color="#FF32CD32" ChartType="Area" ScaleExp="0" />
|
||||
<Serie MetricName="# Lines of Code (NotMyCode)" MetricUnit="Loc" Color="#FFA9A9A9" ChartType="Area" ScaleExp="0" />
|
||||
<Serie MetricName="# Lines of Comments" MetricUnit="Lines" Color="#FF008000" ChartType="Line" ScaleExp="0" />
|
||||
</Chart>
|
||||
<Chart Name="% Coverage and % Debt" ShowInReport="True">
|
||||
<Serie MetricName="Percentage Code Coverage" MetricUnit="%" Color="#FF32CD32" ChartType="Area" ScaleExp="0" />
|
||||
<Serie MetricName="Percentage Debt (Metric)" MetricUnit="%" Color="#FFFF0000" ChartType="Line" ScaleExp="0" />
|
||||
</Chart>
|
||||
<Chart Name="Issues" ShowInReport="True">
|
||||
<Serie MetricName="# New Issues since Baseline" MetricUnit="issues" Color="#FFFF0000" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="# Issues Fixed since Baseline" MetricUnit="issues" Color="#FF32CD32" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="# Blocker/Critical/High Issues" MetricUnit="issues" Color="#FFFF8C00" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="# Issues" MetricUnit="issues" Color="#FFFFD700" ChartType="Line" ScaleExp="-2" />
|
||||
</Chart>
|
||||
<Chart Name="Rules" ShowInReport="True">
|
||||
<Serie MetricName="# Rules" MetricUnit="Rules" Color="#FF66CDAA" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="# Rules Violated" MetricUnit="Rules" Color="#FFFF8C00" ChartType="Area" ScaleExp="0" />
|
||||
<Serie MetricName="# Critical Rules Violated" MetricUnit="Rules" Color="#FFFF0000" ChartType="Area" ScaleExp="0" />
|
||||
</Chart>
|
||||
<Chart Name="Quality Gates" ShowInReport="True">
|
||||
<Serie MetricName="# Quality Gates Fail" MetricUnit="quality gates" Color="#FFFF0000" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="# Quality Gates Warn" MetricUnit="quality gates" Color="#FFFF8C00" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="# Quality Gates" MetricUnit="quality gates" Color="#FF32CD32" ChartType="Line" ScaleExp="0" />
|
||||
</Chart>
|
||||
<Chart Name="Debt" ShowInReport="True">
|
||||
<Serie MetricName="Debt (Metric)" MetricUnit="man-days" Color="#FFFF0000" ChartType="Line" ScaleExp="0" />
|
||||
<Serie MetricName="Annual Interest (Metric)" MetricUnit="man-days" Color="#FFFF8C00" ChartType="Line" ScaleExp="0" />
|
||||
</Chart>
|
||||
</TrendMetrics>
|
||||
<GitHub Account="" Repo="" />
|
||||
<IssueImport ResolveSarifInSolutionDirectories="True" />
|
||||
<HistoricAnalysisResult PersistRecurrence="3" UseCustomDir="False" CustomDir="" RetentionNDays="60" />
|
||||
<SourceFileRebasing FromPath="" ToPath="" />
|
||||
<PathVariables />
|
||||
<RuleFiles />
|
||||
<GraphFiles />
|
||||
<ProjectRules AreActive="True" QueryPersistenceKind="PersistOnlyQueryIdForUntouchedQueries" />
|
||||
<ProjectDebtSettings DebtSettingsStorage="0" SettingsFilePath="">
|
||||
<DebtSettings>
|
||||
<DebtFactor>1</DebtFactor>
|
||||
<AnnualInterestFactor>1</AnnualInterestFactor>
|
||||
<DebtDefault>0</DebtDefault>
|
||||
<AnnualInterestDefault>0</AnnualInterestDefault>
|
||||
<DebtStringFormat>$ManDay$</DebtStringFormat>
|
||||
<MoneyPerManHour>50</MoneyPerManHour>
|
||||
<Currency>USD</Currency>
|
||||
<CurrencyLocation>After</CurrencyLocation>
|
||||
<EstimatedNumberOfManDayToDevelop1000LogicalLinesOfCode>18</EstimatedNumberOfManDayToDevelop1000LogicalLinesOfCode>
|
||||
<NumberOfWorkDayPerYear>240</NumberOfWorkDayPerYear>
|
||||
<NumberOfWorkHourPerDay>8</NumberOfWorkHourPerDay>
|
||||
<A2B_RatingThreshold>5</A2B_RatingThreshold>
|
||||
<B2C_RatingThreshold>10</B2C_RatingThreshold>
|
||||
<C2D_RatingThreshold>20</C2D_RatingThreshold>
|
||||
<D2E_RatingThreshold>50</D2E_RatingThreshold>
|
||||
<Low2Medium_SeverityThreshold>1200000000</Low2Medium_SeverityThreshold>
|
||||
<Medium2High_SeverityThreshold>12000000000</Medium2High_SeverityThreshold>
|
||||
<High2Critical_SeverityThreshold>72000000000</High2Critical_SeverityThreshold>
|
||||
<Critical2Blocker_SeverityThreshold>360000000000</Critical2Blocker_SeverityThreshold>
|
||||
</DebtSettings>
|
||||
</ProjectDebtSettings><Queries>
|
||||
<Group Name="Custom Rules" Active="True" ShownInReport="False">
|
||||
<!-- ND1000: Avoid types too big - threshold increased to 500 for complex financial indicators -->
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[// <Name>ND1000: Avoid types too big</Name>
|
||||
warnif count > 0
|
||||
from t in JustMyCode.Types
|
||||
where t.NbLinesOfCode > 500 &&
|
||||
!t.IsGeneratedByCompiler
|
||||
let loc = t.NbLinesOfCode
|
||||
orderby loc descending
|
||||
select new {
|
||||
t,
|
||||
loc,
|
||||
t.Methods,
|
||||
t.Fields
|
||||
}
|
||||
// This rule identifies types that are too large and should be split into smaller, more focused types.
|
||||
// Threshold increased from default 200 to 500 to accommodate complex financial algorithm classes.
|
||||
// <Debt>10 min per issue</Debt>
|
||||
]]></Query>
|
||||
<!-- ND1004: Avoid methods with too many parameters - threshold increased to 8 for OHLCV data methods -->
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[// <Name>ND1004: Avoid methods with too many parameters</Name>
|
||||
warnif count > 0
|
||||
from m in JustMyCode.Methods
|
||||
where m.NbParameters > 8 &&
|
||||
!m.IsGeneratedByCompiler
|
||||
let np = m.NbParameters
|
||||
orderby np descending
|
||||
select new {
|
||||
m,
|
||||
np,
|
||||
m.NbLinesOfCode
|
||||
}
|
||||
// This rule identifies methods with too many parameters.
|
||||
// Threshold increased from default 5 to 8 to accommodate OHLCV bar data (6 values + time + flags).
|
||||
// <Debt>5 min per issue</Debt>
|
||||
]]></Query>
|
||||
</Group>
|
||||
<Group Name="Quality Gates" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Quality Gates Evolution$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage Coverage$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage Coverage on New Code$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage Coverage on Refactored Code$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Blocker Issues$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Critical Issues$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New Blocker / Critical / High Issues$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Critical Rules Violated$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Treat Compiler Warnings as Error$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage Debt$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Debt$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New Debt since Baseline$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Debt Rating per Namespace$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Annual Interest$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New Annual Interest since Baseline$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Unnecessary NDepend SuppressMessageAttribute Usage$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Hot Spots" Active="True" ShownInReport="True">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Types Hot Spots$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Types to Fix Priority$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Issues to Fix Priority$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Debt and Issues per Rule$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New Debt and Issues per Rule$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Debt and Issues per Code Element$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New Debt and Issues per Code Element$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Code Smells" Active="True" ShownInReport="False">
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1000$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1001$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1002$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1003$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1004$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1005$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1006$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1007$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1008$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1009$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Code Smells Regression" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1100$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1101$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1102$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1103$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1104$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1105$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1106$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1107$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1108$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Object Oriented Design" Active="True" ShownInReport="True">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1200$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1201$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1202$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1203$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1204$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1205$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1206$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1207$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1208$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1209$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1210$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1211$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1212$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1213$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Design" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1300$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1301$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1302$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1303$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1304$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1305$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1306$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1307$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1308$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1309$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1310$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1311$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1312$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1313$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1314$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Architecture" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1400$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1401$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1402$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1403$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1404$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1405$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1406$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1407$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1410$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1408$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1409$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9900$]]></Query>
|
||||
</Group>
|
||||
<Group Name="API Breaking Changes" Active="True" ShownInReport="True">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1500$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1501$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1502$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1503$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1504$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1505$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$API: New publicly visible types$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$API: New publicly visible methods$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$API: New publicly visible fields$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Code Coverage" Active="True" ShownInReport="True">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1600$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1601$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1602$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1603$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1604$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1605$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1606$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1607$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1608$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1609$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1610$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Test Methods$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods directly called by test Methods$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods directly and indirectly called by test Methods$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Dead Code" Active="True" ShownInReport="True">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1700$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1701$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1702$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1703$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Security" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND3120$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND3121$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3100$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3101$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3102$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3103$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3104$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3105$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3106$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3107$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3108$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Visibility" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1800$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1801$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1802$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1803$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1804$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1805$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1806$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1807$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1808$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1809$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1810$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods that should be declared as 'public' in C#, 'Public' in VB.NET$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Immutability" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1900$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND1901$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1902$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1903$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1914$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1904$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1905$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1906$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1907$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1908$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1909$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1910$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1911$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1912$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND1913$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Naming Conventions" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2000$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2001$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2002$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2003$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2004$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2005$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2006$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2007$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2008$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2009$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2010$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2011$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2012$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2013$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2014$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2015$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2016$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2017$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2018$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2019$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2020$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2021$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2022$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Source Files Organization" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2100$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2101$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2102$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2103$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2104$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2105$]]></Query>
|
||||
</Group>
|
||||
<Group Name=".NET Framework Usage" Active="True" ShownInReport="False">
|
||||
<Group Name="System" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2200$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2201$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2202$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2203$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2204$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2205$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2206$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2207$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2208$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2209$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2210$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2211$]]></Query>
|
||||
</Group>
|
||||
<Group Name="System.Collections" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2300$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2301$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2302$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2303$]]></Query>
|
||||
</Group>
|
||||
<Group Name="System.Runtime.InteropServices" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2400$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2401$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2402$]]></Query>
|
||||
</Group>
|
||||
<Group Name="System.Threading" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2500$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2501$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2502$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2503$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="True"><![CDATA[$ND2504$]]></Query>
|
||||
<Query Active="False" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2505$]]></Query>
|
||||
</Group>
|
||||
<Group Name="System.Xml" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2600$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2601$]]></Query>
|
||||
</Group>
|
||||
<Group Name="System.Globalization" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2700$]]></Query>
|
||||
</Group>
|
||||
<Group Name="System.Reflection" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2800$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2801$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2802$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Microsoft.Contracts" Active="True" ShownInReport="False">
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND2900$]]></Query>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group Name="API Usage" Active="True" ShownInReport="False">
|
||||
<Group Name="Unity" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3200$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3201$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3202$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3203$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3204$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3205$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3206$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3207$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3208$]]></Query>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group Name="Defining JustMyCode" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3000$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3001$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3002$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3003$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND3004$]]></Query>
|
||||
<Query Active="False" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$JustMyCode code elements$]]></Query>
|
||||
<Query Active="False" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$NotMyCode code elements$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Trend Metrics" Active="True" ShownInReport="False">
|
||||
<Group Name="Issues" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# New Issues since Baseline$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues Fixed since Baseline$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues Worsened since Baseline$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues with severity Blocker$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues with severity Critical$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues with severity High$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues with severity Medium$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues with severity Low$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Blocker/Critical/High Issues$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Issues$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Suppressed Issues$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Rules" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Rules$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Rules Violated$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Critical Rules Violated$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Quality Gates" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Quality Gates$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Quality Gates Warn$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Quality Gates Fail$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Debt" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage Debt (Metric)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Debt (Metric)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New Debt since Baseline (Metric)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Annual Interest (Metric)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New Annual Interest since Baseline (Metric)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Breaking Point$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Breaking Point of Blocker / Critical / High Issues$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Code Size" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code (JustMyCode)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code (NotMyCode)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code Added since the Baseline$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Source Files$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Line Feed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# IL Instructions$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# IL Instructions (NotMyCode)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Comments$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage of Comments$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Assemblies$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Namespaces$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Types$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Public Types$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Classes$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Abstract Classes$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Interfaces$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Structures$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Abstract Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Concrete Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Fields$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Maximum and Average" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max # Lines of Code for Methods (JustMyCode)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average # Lines of Code for Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average # Lines of Code for Methods with at least 3 Lines of Code$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max # Lines of Code for Types (JustMyCode)$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average # Lines of Code for Types$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max Cyclomatic Complexity for Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average Cyclomatic Complexity for Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max IL Cyclomatic Complexity for Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average IL Cyclomatic Complexity for Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max IL Nesting Depth for Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average IL Nesting Depth for Methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max # of Methods for Types$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average # Methods for Types$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max # of Methods for Interfaces$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average # Methods for Interfaces$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Coverage" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage Code Coverage$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code Covered$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code Not Covered$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code Uncoverable$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code in Types 100% Covered$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of Code in Methods 100% Covered$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Max C.R.A.P Score$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Average C.R.A.P Score$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Percentage JustMyCode Coverage$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of JustMyCode Covered$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Lines of JustMyCode Not Covered$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Third-Party Usage" Active="True" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Third-Party Assemblies Used$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Third-Party Namespaces Used$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Third-Party Types Used$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Third-Party Methods Used$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Third-Party Fields Used$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$# Third-Party Code Elements Used$]]></Query>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group Name="Code Diff Summary" Active="True" ShownInReport="True">
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New assemblies$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Assemblies removed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Assemblies where code was changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New namespaces$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Namespaces removed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Namespaces where code was changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New types$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Types removed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Types where code was changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Heuristic to find types moved from one namespace or assembly to another$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Types directly using one or several types changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Types indirectly using one or several types changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New methods$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods removed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods where code was changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods directly calling one or several methods changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods indirectly calling one or several methods changed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$New fields$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Fields removed$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Third party types that were not used and that are now used$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Third party types that were used and that are not used anymore$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Third party methods that were not used and that are now used$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Third party methods that were used and that are not used anymore$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Third party fields that were not used and that are now used$]]></Query>
|
||||
<Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Third party fields that were used and that are not used anymore$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Statistics" Active="False" ShownInReport="False">
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Most used types (Rank)$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Most used methods (Rank)$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Most used assemblies (#AssembliesUsingMe)$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Most used namespaces (#NamespacesUsingMe )$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Most used types (#TypesUsingMe )$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Most used methods (#MethodsCallingMe )$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Namespaces that use many other namespaces (#NamespacesUsed )$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Types that use many other types (#TypesUsed )$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$Methods that use many other methods (#MethodsCalled )$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$High-level to low-level assemblies (Level)$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$High-level to low-level namespaces (Level)$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$High-level to low-level types (Level)$]]></Query>
|
||||
<Query Active="True" DisplayList="False" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$High-level to low-level methods (Level)$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Samples of Custom rules" Active="False" ShownInReport="False">
|
||||
<Group Name="Check Architecture" Active="False" ShownInReport="False">
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9901$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9902$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9903$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9904$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9905$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9906$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9907$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9908$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9909$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9910$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Check Coverage on particular Code Elements" Active="False" ShownInReport="False">
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9911$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9912$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9913$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9914$]]></Query>
|
||||
</Group>
|
||||
<Group Name="Custom Naming Conventions" Active="False" ShownInReport="False">
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9915$]]></Query>
|
||||
<Query Active="False" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[$ND9916$]]></Query>
|
||||
</Group>
|
||||
</Group>
|
||||
</Queries></NDepend>
|
||||
@@ -25,6 +25,7 @@ from . import ( # noqa: F401
|
||||
cycles,
|
||||
dynamics,
|
||||
errors,
|
||||
feeds,
|
||||
filters,
|
||||
momentum,
|
||||
numerics,
|
||||
@@ -36,6 +37,7 @@ from . import ( # noqa: F401
|
||||
volatility,
|
||||
volume,
|
||||
)
|
||||
from .feeds import * # noqa: F401, F403 — re-export gbm() at top level
|
||||
|
||||
from ._compat import ALIASES, get_compat
|
||||
from ._bridge import (
|
||||
@@ -54,6 +56,8 @@ __all__ = [
|
||||
"cycles",
|
||||
"dynamics",
|
||||
"errors",
|
||||
"feeds",
|
||||
"gbm",
|
||||
"filters",
|
||||
"momentum",
|
||||
"numerics",
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
"""quantalib.feeds — synthetic market data generators.
|
||||
|
||||
Vectorized NumPy port of the C# `GBM` feed (lib/feeds/gbm/gbm.cs). No native
|
||||
FFI call is involved: the entire bar sequence is generated with array
|
||||
operations (cumsum / exp / rng draws), so there is no per-bar Python-loop
|
||||
overhead — the same trade that makes the .NET Batch paths fast.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
|
||||
__all__ = ["gbm"]
|
||||
|
||||
# 252 trading days * 6.5 trading hours/day * 60 minutes/hour
|
||||
_MINUTES_PER_YEAR = 252.0 * 6.5 * 60.0
|
||||
|
||||
|
||||
def gbm(
|
||||
n: int,
|
||||
start_price: float = 100.0,
|
||||
mu: float = 0.05,
|
||||
sigma: float = 0.2,
|
||||
timeframe_minutes: float = 1.0,
|
||||
seed: int | None = None,
|
||||
) -> dict[str, NDArray[np.float64]]:
|
||||
"""Generate `n` synthetic OHLCV bars via Geometric Brownian Motion.
|
||||
|
||||
Mirrors the drift/volatility scaling and OHLC construction of the C#
|
||||
`GBM` feed, but computes the whole series in one vectorized pass instead
|
||||
of bar-by-bar `Next()` calls.
|
||||
|
||||
Args:
|
||||
n: Number of bars to generate. Must be positive.
|
||||
start_price: Initial price (must be positive and finite).
|
||||
mu: Annual drift/return rate.
|
||||
sigma: Annual volatility (must be non-negative and finite).
|
||||
timeframe_minutes: Bar duration in minutes (must be positive).
|
||||
seed: Optional random seed for reproducibility.
|
||||
|
||||
Returns:
|
||||
dict with keys "open", "high", "low", "close", "volume", each a
|
||||
float64 NumPy array of length `n`.
|
||||
"""
|
||||
if n <= 0:
|
||||
raise ValueError("n must be positive")
|
||||
if start_price <= 0 or not np.isfinite(start_price):
|
||||
raise ValueError("start_price must be positive and finite")
|
||||
if not np.isfinite(mu):
|
||||
raise ValueError("mu must be finite")
|
||||
if sigma < 0 or not np.isfinite(sigma):
|
||||
raise ValueError("sigma must be non-negative and finite")
|
||||
if timeframe_minutes <= 0:
|
||||
raise ValueError("timeframe_minutes must be positive")
|
||||
|
||||
rng = np.random.default_rng(seed)
|
||||
|
||||
dt = timeframe_minutes / _MINUTES_PER_YEAR
|
||||
drift = (mu - 0.5 * sigma * sigma) * dt
|
||||
vol = sigma * np.sqrt(dt)
|
||||
|
||||
log_returns = drift + vol * rng.standard_normal(n)
|
||||
close = start_price * np.exp(np.cumsum(log_returns))
|
||||
|
||||
# Fall back to the previous price on any non-finite/non-positive draw,
|
||||
# matching the C# guard in GBM.Next(). Rare, so a short scalar pass is fine.
|
||||
bad = ~np.isfinite(close) | (close <= 0)
|
||||
if bad.any():
|
||||
last = start_price
|
||||
for i in range(n):
|
||||
if bad[i]:
|
||||
close[i] = last
|
||||
last = close[i]
|
||||
|
||||
open_ = np.empty(n, dtype=np.float64)
|
||||
open_[0] = start_price
|
||||
open_[1:] = close[:-1]
|
||||
|
||||
hi_base = np.maximum(open_, close)
|
||||
lo_base = np.minimum(open_, close)
|
||||
|
||||
high = np.maximum(hi_base * (1.0 + rng.random(n) * 0.01), hi_base)
|
||||
low = np.maximum(np.minimum(lo_base * (1.0 - rng.random(n) * 0.01), lo_base), np.finfo(np.float64).tiny)
|
||||
|
||||
volume = 1000.0 + rng.random(n) * 1000.0
|
||||
|
||||
return {
|
||||
"open": open_,
|
||||
"high": high,
|
||||
"low": low,
|
||||
"close": close,
|
||||
"volume": volume,
|
||||
}
|
||||