This commit is contained in:
2024-02-23 06:53:16 -05:00
commit dbdccce727
1094 changed files with 57645 additions and 0 deletions

330
.gitignore vendored Normal file
View File

@@ -0,0 +1,330 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/

20
App.xaml Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Navigator.App">
<Application.Resources>
<ResourceDictionary>
<!--Global Styles-->
<Color x:Key="NavigationPrimary">#2196F3</Color>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{StaticResource NavigationPrimary}" />
<Setter Property="BarTextColor" Value="White" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>

38
App.xaml.cs Normal file
View File

@@ -0,0 +1,38 @@
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Navigator.Services;
using Navigator.Views;
using MarketData.Service;
using Navigator.Utils;
namespace Navigator
{
public partial class App : Application
{
public App()
{
InitializeComponent();
DependencyService.Register<MockDataStore>();
if(!DesignMode.IsDesignModeEnabled)
{
if(MarketDataServiceClient.IsWiFiNetwork())MarketDataServiceClient.GetInstance().SetUrl(AppSettingsManager.Settings["Service_Local"],AppSettingsManager.Settings["ServiceUser"]);
else MarketDataServiceClient.GetInstance().SetUrl(AppSettingsManager.Settings["Service_Network"],AppSettingsManager.Settings["ServiceUser"]);
}
MainPage = new MainPage();
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
}

5
AppSettings.json Normal file
View File

@@ -0,0 +1,5 @@
{
"Service_Local": "http://192.168.0.73:8000",
"Service_Network" : "http://73.245.214.234:8000",
"ServiceUser" : "sean"
}

3
AssemblyInfo.cs Normal file
View File

@@ -0,0 +1,3 @@
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]

View File

@@ -0,0 +1,32 @@
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Text;
namespace DataDisplay.Common
{
public class DrawingHelper
{
private DrawingHelper()
{
}
public static void DrawIsoTriangle(SKCanvas canvas, SKPoint origin, int length, SKPaint paintStroke, SKPaint paintFill)
{
SKPath path = new SKPath();
float lengthF = (float)length;
float hLength = lengthF / 2f;
float height = (float)Math.Sqrt(Math.Pow(lengthF, 2) - Math.Pow(hLength, 2));
height/=1.15f; // reduce the height by 15%
path.MoveTo(origin.X, origin.Y);
path.LineTo(origin.X - hLength, origin.Y + height);
path.LineTo(origin.X + hLength, origin.Y + height);
path.LineTo(origin.X, origin.Y);
path.Close();
canvas.DrawPath(path, paintStroke);
canvas.DrawPath(path, paintFill);
}
}
}

View File

@@ -0,0 +1,162 @@
using MarketData.Utils;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace DataDisplay.Common
{
public class GridLines
{
public delegate Type GetXDataType();
public delegate Type GetYDataType();
public delegate String XDataFormatter(Object data); // custom formatter for XData
public delegate String YDataFormatter(Object data); // custom formatter for YData
private SKPaint paintGrid=new SKPaint{Style=SKPaintStyle.Stroke,Color=new SKColor((uint)SKColors.LightGray),StrokeWidth=1f};
private SKPaint paintAxis=new SKPaint{Style=SKPaintStyle.Stroke,Color=new SKColor((uint)SKColors.Black),StrokeWidth=3f};
private SKPaint paintHorizontalLabelText=new SKPaint{TextSize=24f,IsAntialias=true,Color=new SKColor((uint)SKColors.Black),IsStroke=false,Typeface=SKTypeface.FromFamilyName("Calibri",SKFontStyleWeight.Bold,SKFontStyleWidth.Normal,SKFontStyleSlant.Upright)}; // dates
private SKPaint paintVerticalLabelText=new SKPaint{TextSize=24f,IsAntialias=true,Color=new SKColor((uint)SKColors.Black),IsStroke=false,Typeface=SKTypeface.FromFamilyName("Calibri",SKFontStyleWeight.Bold,SKFontStyleWidth.Normal,SKFontStyleSlant.Upright)}; // values
private GetXDataType getXDataType=null;
private GetYDataType getYDataType=null;
private XDataFormatter xDataFormatter;
private YDataFormatter yDataFormatter;
private Dictionary<String,String> uniqueVerticalLabels;
private Dictionary<String,String> uniqueHorizontalLabels;
public GridLines(double xGridLines,double yGridLines)
{
XGridLines=xGridLines;
YGridLines=yGridLines;
uniqueVerticalLabels=new Dictionary<String,String>();
uniqueHorizontalLabels=new Dictionary<String,String>();
}
public double XGridLines{get;private set;}
public double YGridLines{get;private set;}
public GetXDataType AssignXDataType
{
get{return getXDataType;}
set{getXDataType=value;}
}
public GetYDataType AssignGetYDataType
{
get{return getYDataType;}
set{getYDataType=value;}
}
public XDataFormatter AssignXDataFormatter
{
get{return xDataFormatter;}
set{xDataFormatter=value;}
}
public YDataFormatter AssignYDataFormatter
{
get{return yDataFormatter;}
set{yDataFormatter=value;}
}
public void Render(SKCanvas canvas,PointMapping pointMapping,SKPaint axisPaint=null,SKPaint gridPaint=null)
{
if(null==axisPaint)axisPaint=paintAxis;
if(null==gridPaint)gridPaint=paintGrid;
SKPoint p1;
SKPoint p2;
double xLineFactor = pointMapping.XRange/XGridLines;
double yLineFactor = pointMapping.YRange/YGridLines;
if(0==xLineFactor)xLineFactor=.01;
if(0==yLineFactor)yLineFactor=.01;
// Draw horizontal line grid - the labels go along the left
for (double yIndex = pointMapping.YDataExtentMin; yIndex <= pointMapping.YDataExtent+.05; yIndex += yLineFactor)
{
p1 = pointMapping.MapPoint(new SKPoint((float)pointMapping.XDataExtentMin, (float)yIndex));
p2 = pointMapping.MapPoint(new SKPoint((float)pointMapping.XDataExtent, (float)yIndex));
if(yIndex==pointMapping.YDataExtentMin)canvas.DrawPoints(SKPointMode.Polygon, new SKPoint[] { p1, p2 }, axisPaint);
else canvas.DrawPoints(SKPointMode.Polygon, new SKPoint[] { p1, p2 }, gridPaint);
p1.X=0f;
DisplayXAxisLabel(canvas,pointMapping,p1,yIndex);
}
// Draw vertical line grid - the labels go along the bottom
for (double xIndex = pointMapping.XDataExtentMin; xIndex <= pointMapping.XDataExtent+.05; xIndex += xLineFactor)
{
p1 = pointMapping.MapPoint(new SKPoint((float)xIndex,(float)pointMapping.YDataExtentMin));
p2 = pointMapping.MapPoint(new SKPoint((float)xIndex, (float)pointMapping.YDataExtent));
if(xIndex==pointMapping.XDataExtentMin)canvas.DrawPoints(SKPointMode.Polygon, new SKPoint[] { p1, p2 }, axisPaint);
else canvas.DrawPoints(SKPointMode.Polygon, new SKPoint[] { p1, p2 }, gridPaint);
p1.Y=(float)pointMapping.Height;
DisplayYAxisLabel(canvas,pointMapping,p1,xIndex);
}
}
// The labels along the left of the chart
private void DisplayXAxisLabel(SKCanvas canvas,PointMapping pointMapping,SKPoint p1,double yIndex)
{
String strLabel;
double percentage=(yIndex - pointMapping.YDataExtentMin) / pointMapping.YRange;
Type dataType=typeof(double);
if(null!=getYDataType)dataType=getYDataType();
if(dataType.Equals(typeof(DateTime)))
{
DateTime axisDate=new DateTime((long)((pointMapping.YDataExtentMin+(pointMapping.YRange*percentage))*10000000000.0));
if(null!=yDataFormatter)strLabel=yDataFormatter(axisDate);
else strLabel=Utility.DateTimeToStringMMSYY(axisDate);
}
else if(dataType.Equals(typeof(double)))
{
double value=pointMapping.YDataExtentMin+(pointMapping.YRange*percentage);
if(null!=yDataFormatter)strLabel=yDataFormatter(value);
else
{
if(value>=1000)strLabel=Utility.FormatNumber(value,0,true);
else strLabel=Utility.FormatNumber(value,2,true);
}
}
else
{
double value=pointMapping.YDataExtentMin+(pointMapping.YRange*percentage);
strLabel=Utility.FormatNumber(value,0,true);
}
if(uniqueVerticalLabels.ContainsKey(strLabel))return;
uniqueVerticalLabels.Add(strLabel,strLabel);
if(null!=strLabel)canvas.DrawText(strLabel, p1, paintVerticalLabelText);
}
// The labels along the bottom of the chart
private void DisplayYAxisLabel(SKCanvas canvas,PointMapping pointMapping,SKPoint p1,double xIndex)
{
String strLabel=null;
double percentage=(xIndex-pointMapping.XDataExtentMin)/pointMapping.XRange;
Type dataType=typeof(double);
if(null!=getXDataType())dataType=getXDataType();
if (dataType.Equals(typeof(DateTime)))
{
DateTime axisDate=new DateTime((long)((pointMapping.XDataExtentMin+(pointMapping.XRange*percentage))*10000000000.0));
if(null!=xDataFormatter)strLabel=xDataFormatter(axisDate);
else strLabel=Utility.DateTimeToStringMMSYY(axisDate);
}
else if(dataType.Equals(typeof(double)))
{
double value=pointMapping.XDataExtentMin+(pointMapping.XRange*percentage);
if(null!=xDataFormatter)strLabel=xDataFormatter(value);
else
{
if(value>=1000)strLabel=Utility.FormatNumber(value,0,true);
else strLabel=Utility.FormatNumber(value,2,true);
}
}
else
{
double value=pointMapping.XDataExtentMin+(pointMapping.XRange*percentage);
strLabel=Utility.FormatNumber(value,0,true);
}
if(uniqueHorizontalLabels.ContainsKey(strLabel))return;
uniqueHorizontalLabels.Add(strLabel,strLabel);
if(null!=strLabel)canvas.DrawText(strLabel, p1, paintHorizontalLabelText);
}
}
}

View File

@@ -0,0 +1,50 @@
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Text;
namespace DataDisplay.Common
{
public class PointMapping
{
public PointMapping(double width,double height,double xDataExtent,double xDataExtentMin,double yDataExtent,double yDataExtentMin,double xMarginExtent=0.00,double yMarginExtent=0.00)
{
Width=width;
Height=height;
XMargin=xMarginExtent;
YMargin=yMarginExtent;
XDataExtent=xDataExtent;
XDataExtentMin=xDataExtentMin;
YDataExtent=yDataExtent;
YDataExtentMin=yDataExtentMin;
XScalingFactor=(Width-(XMargin*2))/(XDataExtent-XDataExtentMin);
YScalingFactor=(Height-(YMargin*2))/(YDataExtent-YDataExtentMin);
}
// MapPoint will both scale the given point and translate the given point from an upper left origin system to a bottom left origin system
public SKPoint MapPoint(SKPoint sourcePoint)
{
SKPoint mappedPoint=new SKPoint((float)((sourcePoint.X-XDataExtentMin)*XScalingFactor),(float)(Height-((sourcePoint.Y-YDataExtentMin)*YScalingFactor)));
mappedPoint.X+=(float)XMargin; // offset by the xMargin
mappedPoint.Y-=(float)YMargin; // offset by the yMargin
return mappedPoint;
}
// TranslatePoint will only translate the given point from an upper left origin system to a bottom left origin system
public SKPoint TranslatePoint(SKPoint sourcePoint)
{
SKPoint mappedPoint=new SKPoint((float)sourcePoint.X,(float)(Height-sourcePoint.Y-1));
return mappedPoint;
}
public double Width{get;private set;}
public double Height{get;private set;}
public double XDataExtent{get;private set;}
public double XDataExtentMin{get;private set;}
public double XRange{get{return XDataExtent-XDataExtentMin;}}
public double YDataExtent{get;private set;}
public double YDataExtentMin{get;private set;}
public double YRange{get{return YDataExtent-YDataExtentMin;}}
public double XMargin{get;private set;}
public double YMargin{get;private set;}
public double XScalingFactor{get;private set;}
public double YScalingFactor{get;private set;}
}
}

View File

@@ -0,0 +1,58 @@
using SkiaSharp.Views.Forms;
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace DataDisplay.Controls
{
public class CanvasView : SKCanvasView
{
public static readonly BindableProperty RendererProperty = BindableProperty.Create(
nameof(Renderer),
typeof(Renderers.IRenderer),
typeof(CanvasView),
null,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: (bindable, oldValue, newValue) =>
{
((CanvasView)bindable).RendererChanged((Renderers.IRenderer)oldValue, (Renderers.IRenderer)newValue);
});
// callback appelée lors de la modificiation de la propriété "Renderer"
void RendererChanged(Renderers.IRenderer currentRenderer, Renderers.IRenderer newRenderer)
{
if (currentRenderer != newRenderer)
{
// détacher l'événement de l'ancien renderer
if (currentRenderer != null)
currentRenderer.RefreshRequested -= Renderer_RefreshRequested;
// attacher l'événement du nouveau renderer
if (newRenderer != null)
newRenderer.RefreshRequested += Renderer_RefreshRequested;
// rafraichir le contrôle
InvalidateSurface();
}
}
// Causes refreshing during an event triggered by the ISKRenderer interface
void Renderer_RefreshRequested(object sender, EventArgs e)
{
InvalidateSurface();
}
protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
if (null == Renderer) return;
Renderer.PaintSurface(e.Surface, e.Info);
}
public Renderers.IRenderer Renderer
{
get { return (Renderers.IRenderer)GetValue(RendererProperty); }
set { SetValue(RendererProperty, value); }
}
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SkiaSharp.Views.Forms" Version="1.68.3" />
</ItemGroup>
<ItemGroup>
<Folder Include="Renderers\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MarketDataLib\MarketDataLib.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30204.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataDisplay", "DataDisplay.csproj", "{11EFBEE6-2BFD-4D05-AD34-C5B0A894EB99}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{11EFBEE6-2BFD-4D05-AD34-C5B0A894EB99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11EFBEE6-2BFD-4D05-AD34-C5B0A894EB99}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11EFBEE6-2BFD-4D05-AD34-C5B0A894EB99}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11EFBEE6-2BFD-4D05-AD34-C5B0A894EB99}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DFC8F4F9-9B94-400D-8E39-6561192D5486}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Collections;
using Xamarin.Forms;
using SkiaSharp;
namespace DataDisplay.DataSource
{
public class DataSourceHelper
{
private DataSourceHelper()
{
}
public static IEnumerable<SKPoint> GetPoints(IPointDataSource dataSource)
{
if (dataSource == null) throw new ArgumentNullException("dataSource");
using (IPointEnumerator enumerator = dataSource.GetEnumerator(null))
{
while (enumerator.MoveNext())
{
Point xPoint=new Point();
enumerator.GetCurrent(ref xPoint);
yield return new SKPoint((float)xPoint.X,(float)xPoint.Y);
xPoint=new Point();
}
}
}
}
/// <summary>Data source that is a composer from several other data sources.</summary>
public class CompositeDataSource : IPointDataSource {
/// <summary>Initializes a new instance of the <see cref="CompositeDataSource"/> class</summary>
public CompositeDataSource() { }
public void Clear()
{
dataParts.Clear();
}
/// <summary>
/// Initializes a new instance of the <see cref="CompositeDataSource"/> class.
/// </summary>
/// <param name="dataSources">Data sources.</param>
public CompositeDataSource(params IPointDataSource[] dataSources) {
if (dataSources == null)
throw new ArgumentNullException("dataSources");
foreach (var dataSource in dataSources) {
AddDataPart(dataSource);
}
}
private readonly List<IPointDataSource> dataParts = new List<IPointDataSource>();
public IEnumerable<IPointDataSource> DataParts {
get { return dataParts; }
}
/// <summary>
/// Adds data part.
/// </summary>
/// <param name="dataPart">The data part.</param>
public void AddDataPart(IPointDataSource dataPart) {
if (dataPart == null)
throw new ArgumentNullException("dataPart");
dataParts.Add(dataPart);
dataPart.DataChanged += OnPartDataChanged;
}
private void OnPartDataChanged(object sender, EventArgs e) {
RaiseDataChanged();
}
#region IPointSource Members
public event EventHandler DataChanged;
protected void RaiseDataChanged() {
if (DataChanged != null) {
DataChanged(this, EventArgs.Empty);
}
}
public IPointEnumerator GetEnumerator(BindableObject context) {
return new CompositeEnumerator(this, context);
}
#endregion
private sealed class CompositeEnumerator : IPointEnumerator {
private readonly IEnumerable<IPointEnumerator> enumerators;
public CompositeEnumerator(CompositeDataSource dataSource, BindableObject context) {
enumerators = dataSource.dataParts.Select(part => part.GetEnumerator(context)).ToList();
}
#region IChartPointEnumerator Members
public bool MoveNext() {
bool res = false;
foreach (var enumerator in enumerators) {
res |= enumerator.MoveNext();
}
return res;
}
public void ApplyMappings(BindableObject glyph) {
foreach (var enumerator in enumerators) {
enumerator.ApplyMappings(glyph);
}
}
public void GetCurrent(ref Point p) {
foreach (var enumerator in enumerators) {
enumerator.GetCurrent(ref p);
}
}
public void Dispose() {
foreach (var enumerator in enumerators) {
enumerator.Dispose();
}
}
#endregion
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace DataDisplay.DataSource
{
public static class DataSourceExtensions
{
public static CompositeDataSource Join(this IPointDataSource ds1, IPointDataSource ds2)
{
return new CompositeDataSource(ds1, ds2);
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using Xamarin.Forms;
namespace DataDisplay.DataSource
{
public class EnumerableDataSource<T> : EnumerableDataSourceBase<T>
{
public EnumerableDataSource(IEnumerable<T> data) : base(data) { }
public EnumerableDataSource(IEnumerable data) : base(data) { }
private readonly List<Mapping<T>> mappings = new List<Mapping<T>>();
private Func<T, double> xMapping;
private Func<T, double> yMapping;
private Func<T, Point> xyMapping;
public Func<T, double> XMapping
{
get { return xMapping; }
set { SetXMapping(value); }
}
public Func<T, double> YMapping
{
get { return yMapping; }
set { SetYMapping(value); }
}
public Func<T, Point> XYMapping
{
get { return xyMapping; }
set { SetXYMapping(value); }
}
public void SetXMapping(Func<T, double> mapping)
{
if (mapping == null)
throw new ArgumentNullException("mapping");
this.xMapping = mapping;
RaiseDataChanged();
}
public void SetYMapping(Func<T, double> mapping)
{
if (mapping == null)
throw new ArgumentNullException("mapping");
this.yMapping = mapping;
RaiseDataChanged();
}
public void SetXYMapping(Func<T, Point> mapping)
{
if (mapping == null)
throw new ArgumentNullException("mapping");
this.xyMapping = mapping;
RaiseDataChanged();
}
public void AddMapping(BindableProperty property, Func<T, object> mapping)
{
if (property == null)
throw new ArgumentNullException("property");
if (mapping == null)
throw new ArgumentNullException("mapping");
mappings.Add(new Mapping<T> { Property = property, F = mapping });
}
public override IPointEnumerator GetEnumerator(BindableObject context)
{
return new EnumerablePointEnumerator<T>(this);
}
internal void FillPoint(T elem, ref Point point)
{
if (xyMapping != null)
{
point = xyMapping(elem);
}
else
{
if (xMapping != null)
{
point.X = xMapping(elem);
}
if (yMapping != null)
{
point.Y = yMapping(elem);
}
}
}
internal void ApplyMappings(BindableObject target, T elem)
{
if (target != null)
{
foreach (var mapping in mappings)
{
target.SetValue(mapping.Property, mapping.F(elem));
}
}
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows;
using Xamarin.Forms;
namespace DataDisplay.DataSource
{
/// <summary>Base class for all sources who receive data for charting
/// from any IEnumerable of T</summary>
/// <typeparam name="T">Type of items in IEnumerable</typeparam>
public abstract class EnumerableDataSourceBase<T> : IPointDataSource {
private IEnumerable data;
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
public IEnumerable Data {
get { return data; }
set {
if (value == null)
throw new ArgumentNullException("value");
data = value;
var observableCollection = data as INotifyCollectionChanged;
if (observableCollection != null) {
observableCollection.CollectionChanged += observableCollection_CollectionChanged;
}
}
}
protected EnumerableDataSourceBase(IEnumerable<T> data) : this((IEnumerable)data) { }
protected EnumerableDataSourceBase(IEnumerable data) {
if (data == null)
throw new ArgumentNullException("data");
Data = data;
}
private void observableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
RaiseDataChanged();
}
public event EventHandler DataChanged;
public void RaiseDataChanged() {
if (DataChanged != null) {
DataChanged(this, EventArgs.Empty);
}
}
public abstract IPointEnumerator GetEnumerator(BindableObject context);
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections;
using System.Windows;
using Xamarin.Forms;
namespace DataDisplay.DataSource
{
/// <summary>This enumerator enumerates given enumerable object as sequence of points</summary>
/// <typeparam name="T">Type parameter of source IEnumerable</typeparam>
public sealed class EnumerablePointEnumerator<T> : IPointEnumerator {
private readonly EnumerableDataSource<T> dataSource;
private readonly IEnumerator enumerator;
public EnumerablePointEnumerator(EnumerableDataSource<T> dataSource) {
this.dataSource = dataSource;
enumerator = dataSource.Data.GetEnumerator();
}
public bool MoveNext()
{
try{return enumerator.MoveNext();}
catch(InvalidOperationException){return false;}
}
public void GetCurrent(ref Point p) {
dataSource.FillPoint((T)enumerator.Current, ref p);
}
public void ApplyMappings(BindableObject target) {
dataSource.ApplyMappings(target, (T)enumerator.Current);
}
public void Dispose() {
//enumerator.Reset();
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Windows;
using Xamarin.Forms;
namespace DataDisplay.DataSource
{
/// <summary>Data source that returns sequence of 2D points.</summary>
public interface IPointDataSource
{
/// <summary>Returns object to enumerate points in source.</summary>
IPointEnumerator GetEnumerator(BindableObject context);
/// <summary>This event is raised when contents of source are changed.</summary>
event EventHandler DataChanged;
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Windows;
using Xamarin.Forms;
namespace DataDisplay.DataSource
{
public interface IPointEnumerator : IDisposable {
/// <summary>Move to next point in sequence</summary>
/// <returns>True if successfully moved to next point
/// or false if end of sequence is reached</returns>
bool MoveNext();
/// <summary>Stores current value(s) in given point.</summary>
/// <param name="p">Reference to store value</param>
/// <remarks>Depending on implementing class this method may set only X or Y
/// fields in specified point. That's why GetCurrent is a regular method and
/// not a property as in standard enumerators</remarks>
void GetCurrent(ref Point p);
void ApplyMappings(BindableObject target);
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Windows;
using Xamarin.Forms;
namespace DataDisplay.DataSource
{
/// <summary>Mapping class holds information about mapping of TSource type
/// to some DependencyProperty.</summary>
/// <typeparam name="TSource">Mapping source type.</typeparam>
internal sealed class Mapping<TSource> {
/// <summary>Property that will be set.</summary>
internal BindableProperty Property { get; set; }
/// <summary>Function that computes value for property from TSource type.</summary>
internal Func<TSource, object> F { get; set; }
}
}

View File

@@ -0,0 +1,77 @@
using DataDisplay.Common;
using DataDisplay.DataSource;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataDisplay.Graph
{
public class LineGraph
{
private SKPoint[] points=null;
private CompositeDataSource compositeDataSource;
private SKPaint paint;
public LineGraph(SKPaint paint,CompositeDataSource compositeDataSource)
{
this.compositeDataSource = compositeDataSource;
this.paint=paint;
points=GetSKPoints();
}
public void SetPaint(SKPaint paint)
{
this.paint=paint;
}
public void SetDataSource(CompositeDataSource compositeDataSource)
{
this.compositeDataSource=compositeDataSource;
points=GetSKPoints();
}
public void Render(SKCanvas canvas,PointMapping pointMapping)
{
if(null==points)return;
SKPoint[] mappedPoints = new SKPoint[points.Length];
for (int index = 0; index < points.Length; index++) mappedPoints[index] = pointMapping.MapPoint(points[index]);
canvas.DrawPoints(SKPointMode.Polygon,mappedPoints,paint);
}
public SKPoint[] GetSKPoints()
{
IEnumerable<SKPoint> pointsEnumerable=DataSourceHelper.GetPoints(compositeDataSource);
IEnumerator<SKPoint> pointsEnumerator=pointsEnumerable.GetEnumerator();
List<SKPoint> points=new List<SKPoint>();
while(pointsEnumerator.MoveNext())points.Add(pointsEnumerator.Current);
return points.ToArray();
}
public SKPoint[] SKPoints
{
get{return points;}
private set{;}
}
public double GetXExtent()
{
if(null==points)return 0.00;
double xExtents=points.Max(x=>x.X);
return xExtents;
}
public double GetXExtentMin()
{
if(null==points)return 0.00;
double xExtents=points.Min(x=>x.X);
return xExtents;
}
public double GetYExtent()
{
if(null==points)return 0.00;
double yExtents=points.Max(x=>x.Y);
return yExtents;
}
public double GetYExtentMin()
{
if(null==points)return 0.00;
double yExtents=points.Min(x=>x.Y);
return yExtents;
}
}
}

View File

@@ -0,0 +1,41 @@
//using SkiaSharp;
//using System;
//using System.Collections.Generic;
//using System.Text;
//namespace DataDisplay.Renderers
//{
// class CircleRenderer : IRenderer
// {
// public void PaintSurface(SKSurface surface, SKImageInfo info)
// {
// SKCanvas canvas = surface.Canvas; // récupère le canvas
// canvas.Clear();
// // opérations de dessin, par exemple dessiner un cercle
// // paramètre de remplissage du cercle
// SKPaint fillPaint = new SKPaint
// {
// Style = SKPaintStyle.Fill,
// Color = FillColor
// };
// canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, fillPaint);
// }
// SKColor _fillColor = new SKColor(160, 160, 160);
// public SKColor FillColor
// {
// get => _fillColor;
// set
// {
// if (_fillColor != value)
// {
// _fillColor = value;
// RefreshRequested?.Invoke(this, EventArgs.Empty);
// }
// }
// }
// public event EventHandler RefreshRequested;
// }
//}

View File

@@ -0,0 +1,11 @@
using System;
using SkiaSharp;
namespace DataDisplay.Renderers
{
public interface IRenderer
{
void PaintSurface(SKSurface surface, SKImageInfo info);
event EventHandler RefreshRequested;
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="SkiaSharp.Views.Forms" Version="1.68.3" />
<PackageReference Include="Xamarin.Essentials" Version="1.5.3.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using MarketData.Utils;
using MarketData.Numerical;
namespace MarketData.MarketDataModel
{
public class BollingerBandElementsByDate : Dictionary<DateTime, BollingerBandElement>
{
public BollingerBandElementsByDate()
{
}
}
public class BollingerBands : BollingerBandElements
{
public BollingerBands()
{
}
public BollingerBands(List<BollingerBandElement> bollingerBandElements)
{
foreach(BollingerBandElement bollingerBandElement in bollingerBandElements)Add(bollingerBandElement);
}
public static String GetHeader(int movingAverageDays)
{
StringBuilder sb = new StringBuilder();
sb.Append("Date,Symbol,Open,High,Low,Close,Volume,SMA(").Append(movingAverageDays).Append("),StDev(").Append(movingAverageDays).Append("),K,L,K-1,L+1");
return sb.ToString();
}
public BollingerBandElementsByDate GetBollingerBandElementsByDate()
{
BollingerBandElementsByDate bollingerBandElementsByDate = new BollingerBandElementsByDate();
for (int index = 0; index < Count; index++)
{
BollingerBandElement bollingerBandElement = this[index];
if (!bollingerBandElementsByDate.ContainsKey(bollingerBandElement.Date)) bollingerBandElementsByDate.Add(bollingerBandElement.Date, bollingerBandElement);
}
return bollingerBandElementsByDate;
}
}
public class BollingerBandElements : List<BollingerBandElement>
{
public BollingerBandElements()
{
}
public BollingerBandElements(List<BollingerBandElement> bollingerBandElements)
{
foreach(BollingerBandElement bollingerBandElement in bollingerBandElements)Add(bollingerBandElement);
}
public LeastSquaresResult LeastSquaresFitClose()
{
double[] closingPrices=(from BollingerBandElement bollingerBandElement in this select bollingerBandElement.Close).ToList().ToArray();
LeastSquaresResult leastSquaresResult=Numerics.LeastSquares(closingPrices);
return leastSquaresResult;
}
}
public class BollingerBandElement
{
private DateTime date;
private String symbol;
private double open;
private double high;
private double low;
private double close;
private long volume;
private double smaN;
private double stdevN;
private double k;
private double l;
private double kl1;
private double lp1;
public BollingerBandElement()
{
}
public DateTime Date
{
get { return date; }
set { date = value; }
}
public String Symbol
{
get { return symbol; }
set { symbol = value; }
}
public double Open
{
get { return open; }
set { open = value; }
}
public double High
{
get { return high; }
set { high = value; }
}
public double Low
{
get { return low; }
set { low = value; }
}
public double Close
{
get { return close; }
set { close = value; }
}
public double SMAN
{
get { return smaN; }
set { smaN = value; }
}
public double StDevN
{
get { return stdevN; }
set { stdevN = value; }
}
public long Volume
{
get { return volume; }
set { volume = value; }
}
public double K
{
get { return k; }
set { k = value; }
}
public double L
{
get { return l; }
set { l = value; }
}
public double KL1
{
get { return kl1; }
set { kl1 = value; }
}
public double LP1
{
get { return lp1; }
set { lp1 = value; }
}
public override String ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(Utility.DateTimeToStringMMSDDSYYYY(Date)).Append(",");
sb.Append(Symbol).Append(",");
sb.Append(Open).Append(",");
sb.Append(High).Append(",");
sb.Append(Low).Append(",");
sb.Append(Close).Append(",");
sb.Append(Volume).Append(",");
sb.Append(SMAN).Append(",");
sb.Append(StDevN).Append(",");
sb.Append(K).Append(",");
sb.Append(L).Append(",");
sb.Append(KL1).Append(",");
sb.Append(LP1);
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MarketData.MarketDataModel
{
public class Constants
{
public const String CONST_ALL ="{All}";
public const String CONST_DASHES = "---";
public const String NA = "N.A.";
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MarketData.MarketDataModel
{
public class GainLossSummaryItemCollection : List<GainLossSummaryItem>
{
public GainLossSummaryItemCollection()
{
}
public GainLossSummaryItemCollection(List<GainLossSummaryItem> gainLossSummaryItemCollection)
{
foreach(GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItemCollection)Add(gainLossSummaryItem);
}
public GainLossSummaryItemCollection SortByChange()
{
GainLossSummaryItemCollection gainLossSummaryCollection=new GainLossSummaryItemCollection((from GainLossSummaryItem gainLossSummaryItem in this orderby gainLossSummaryItem.Date descending,gainLossSummaryItem.Change descending, gainLossSummaryItem.Symbol descending select gainLossSummaryItem).ToList());
return gainLossSummaryCollection;
}
}
public class GainLossSummaryItem
{
public GainLossSummaryItem()
{
}
public DateTime Date{get;set;}
public String Symbol{get;set;}
public String CompanyName{get;set;}
public double CurrentGainLoss{get;set;}
public double PreviousGainLoss{get;set;}
public double Change{get;set;}
public double ChangePercent{get;set;}
public bool HasStopLimit{get;set;}
}
}

View File

@@ -0,0 +1,35 @@
using System;
namespace MarketData.MarketDataModel.GainLoss
{
public class DMAValue
{
private DateTime date;
private double value;
private double maValue;
public DMAValue()
{
}
public DMAValue(DateTime date, double value)
{
this.date = date;
this.value = value;
}
public DateTime Date
{
get { return date; }
set { date = value; }
}
public double Value
{
get { return value; }
set { this.value = value; }
}
public double MAValue
{
get { return maValue; }
set { this.maValue = value; }
}
}
}

View File

@@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace MarketData.MarketDataModel.GainLoss
{
public class DMAValues : List<DMAValue>
{
public DMAValues()
{
}
public float[] GetValues(int startIndex, int count)
{
if (startIndex + count > Count) return null;
float[] valuesArray = new float[count];
for (int index = startIndex, arrayIndex = 0; index < startIndex + count; index++, arrayIndex++)
{
valuesArray[arrayIndex] = (float)this[index].Value;
}
return valuesArray;
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
namespace MarketData.MarketDataModel.GainLoss
{
// **************************************************************************************************************************************************************
// *********************************************** G A I N / L O S S C O M P O U N D M O D E L ****************************************
// **************************************************************************************************************************************************************
// This GainLossModel will be used to model the GainLossView in terms of surfacing the Active Gain/Loss, Active Exposure, Active Gain/Loss%, Total Gain/Loss, Total Gain/Loss % data
public class GainLossCompoundModel
{
public DateTime Date{get;set;}
public double ActiveExposure{get;set;}
public double ActiveGainLoss{get;set;}
public double ActiveGainLossPercent{get;set;}
public double TotalGainLoss{get;set;}
public double TotalGainLossPercent{get;set;}
public double TotalDividendsPaid{get;set;}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
namespace MarketData.MarketDataModel.GainLoss
{
// The GainLossCompoundModelCollection contains both the active gain loss and the total gain loss time series data
public class GainLossCompoundModelCollection : List<GainLossCompoundModel>
{
public GainLossCompoundModelCollection()
{
}
public GainLossCompoundModelCollection(List<GainLossCompoundModel> items)
{
foreach(GainLossCompoundModel item in items)Add(item);
}
public GainLossCompoundModelCollection(GainLossCollection activeGainLossCollection,TotalGainLossCollection totalGainLossCollection)
{
if(null==activeGainLossCollection||null==totalGainLossCollection)return;
Dictionary<DateTime,GainLossItem> activeGainLossCollectionByDate=new Dictionary<DateTime,GainLossItem>();
Dictionary<DateTime,TotalGainLossItem> totalGainLossCollectionByDate=new Dictionary<DateTime,TotalGainLossItem>();
foreach(GainLossItem gainLossItem in activeGainLossCollection)if(!activeGainLossCollectionByDate.ContainsKey(gainLossItem.Date))activeGainLossCollectionByDate.Add(gainLossItem.Date,gainLossItem);
foreach(TotalGainLossItem gainLossItem in totalGainLossCollection)if(!totalGainLossCollectionByDate.ContainsKey(gainLossItem.Date))totalGainLossCollectionByDate.Add(gainLossItem.Date,gainLossItem);
List<DateTime> dates=new List<DateTime>(activeGainLossCollectionByDate.Keys);
dates.Sort();
foreach(DateTime date in dates)
{
GainLossItem activeGainLossItem=activeGainLossCollectionByDate[date];
if(!totalGainLossCollectionByDate.ContainsKey(date))continue;
TotalGainLossItem totalGainLossItem=totalGainLossCollectionByDate[date];
GainLossCompoundModel gainLossModel=new GainLossCompoundModel();
gainLossModel.Date=activeGainLossItem.Date;
gainLossModel.ActiveExposure=activeGainLossItem.Exposure;
gainLossModel.ActiveGainLoss=activeGainLossItem.GainLoss;
gainLossModel.ActiveGainLossPercent=activeGainLossItem.GainLossPercent;
gainLossModel.TotalGainLoss=totalGainLossItem.TotalGainLoss;
gainLossModel.TotalGainLossPercent=totalGainLossItem.TotalGainLossPercent;
gainLossModel.TotalDividendsPaid=totalGainLossItem.TotalDividendsPaid;
Add(gainLossModel);
}
}
public DMAValues DMAValuesActiveGainLoss
{
get
{
DMAValues dmaValues = new DMAValues();
foreach (GainLossCompoundModel gainLoss in this)
{
dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.ActiveGainLoss));
}
return dmaValues;
}
}
public DMAValues DMAValuesTotalGainLoss
{
get
{
DMAValues dmaValues = new DMAValues();
foreach (GainLossCompoundModel gainLoss in this)
{
dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.TotalGainLoss));
}
return dmaValues;
}
}
public DMAValues DMAValuesActiveGainLossPercent
{
get
{
DMAValues dmaValues = new DMAValues();
foreach (GainLossCompoundModel gainLoss in this)
{
dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.ActiveGainLossPercent));
}
return dmaValues;
}
}
public DMAValues DMAValuesTotalGainLossPercent
{
get
{
DMAValues dmaValues = new DMAValues();
foreach (GainLossCompoundModel gainLoss in this)
{
dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.TotalGainLossPercent));
}
return dmaValues;
}
}
}
}

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using MarketData.Utils;
namespace MarketData.MarketDataModel.GainLoss
{
// *********************************************************************************************************************************************************************
// ************************************************************************ G A I N L O S S **************************************************************************
// *********************************************************************************************************************************************************************
// This gain loss provides a picture of the Active Gain/Loss. The gain loss on open positions
public class GainLossItem : IComparable
{
private DateTime date;
private double gainLoss;
private double gainLossPercent;
private double exposure;
private double dividends;
private bool valueIsPercent;
public GainLossItem()
{
}
public GainLossItem(DateTime date, double gainLoss,double exposure,bool valueIsPercent)
{
this.date = date;
this.gainLoss = gainLoss;
this.exposure = exposure;
this.valueIsPercent = valueIsPercent;
}
public GainLossItem(DateTime date, double gainLoss,double gainLossPercent,double exposure,bool valueIsPercent)
{
this.date = date;
this.gainLoss = gainLoss;
this.gainLossPercent=gainLossPercent;
this.exposure = exposure;
this.valueIsPercent = valueIsPercent;
}
public GainLossItem(DateTime date, double gainLoss,double gainLossPercent,double exposure,double dividends,bool valueIsPercent)
{
this.date = date;
this.gainLoss = gainLoss;
this.gainLossPercent=gainLossPercent;
this.exposure = exposure;
this.dividends=dividends;
this.valueIsPercent = valueIsPercent;
}
public DateTime Date
{
get { return date; }
}
public double Exposure
{
get
{
return exposure;
}
}
public double GainLoss
{
get { return gainLoss; }
}
public double Dividends
{
get{return dividends;}
}
public double GainLossPercent
{
get { return gainLossPercent; }
}
public bool ValueIsPercent
{
get
{
return valueIsPercent;
}
set
{
valueIsPercent = value;
}
}
public String FormattedGainLoss
{
get
{
if (valueIsPercent) return Utility.FormatNumber(gainLoss);
return Utility.FormatCurrency(gainLoss);
}
}
public int CompareTo(Object obj)
{
if (!obj.GetType().IsInstanceOfType(this)) throw new Exception("Expected GainLoss");
GainLossItem that = (GainLossItem)obj;
return date.CompareTo(that.Date);
}
}
public class GainLossCollection : List<GainLossItem>
{
public GainLossCollection(ICollection<GainLossItem> gainLoss)
: base(gainLoss)
{
}
public DMAValues DMAValues
{
get
{
DMAValues dmaValues = new DMAValues();
foreach (GainLossItem gainLoss in this)
{
dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.GainLoss));
}
return dmaValues;
}
}
}
}

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace MarketData.MarketDataModel.GainLoss
{
// ****************************************************************************************************************************************************
// ********************************************************************** T O T A L G A I N L O S S *************************************************
// ****************************************************************************************************************************************************
// This Gain/Loss provides a picture of the total Gain/Loss. This is Gain/Loss generated by all trades
public class TotalGainLossCollection : List<TotalGainLossItem>
{
public TotalGainLossCollection(ICollection<TotalGainLossItem> gainLoss)
: base(gainLoss)
{
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.IO;
//using MarketData.Utils;
//using System.Collections.ObjectModel;
//using MarketData.Generator.GainLoss;
//using MarketData.DataAccess;
namespace MarketData.MarketDataModel.GainLoss
{
// ****************************************************************************************************************************************************
// ********************************************************************** T O T A L G A I N L O S S *************************************************
// ****************************************************************************************************************************************************
// This Gain/Loss provides a picture of the total Gain/Loss. This is Gain/Loss generated by all trades
public class TotalGainLossItem : IComparable
{
public TotalGainLossItem(DateTime date,double totalGainLoss,double totalGainLossPercent,double totalExposure,double totalMarketValue)
{
Date=date;
TotalGainLoss=totalGainLoss;
TotalExposure=totalExposure;
TotalMarketValue=totalMarketValue;
TotalGainLossPercent=totalGainLossPercent;
}
public TotalGainLossItem(DateTime date,double totalGainLoss,double totalGainLossPercent,double totalExposure,double totalMarketValue,double totalDividendsPaid)
{
Date=date;
TotalGainLoss=totalGainLoss;
TotalExposure=totalExposure;
TotalMarketValue=totalMarketValue;
TotalGainLossPercent=totalGainLossPercent;
TotalDividendsPaid=totalDividendsPaid;
}
public DateTime Date{get;private set;}
public double TotalGainLoss{get;private set;}
public double TotalGainLossPercent{get;private set;}
public double TotalExposure{get;private set;}
public double TotalMarketValue{get;private set;}
public double TotalDividendsPaid{get;private set;}
public int CompareTo(Object obj)
{
if (!obj.GetType().IsInstanceOfType(this)) throw new Exception("Expected GainLoss");
TotalGainLossItem that = (TotalGainLossItem)obj;
return Date.CompareTo(that.Date);
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MarketData.MarketDataModel
{
public class Headlines : List<Headline>
{
}
public class Headline
{
public Headline()
{
}
public Headline(Headline headline)
{
Date=headline.Date;
Symbol=headline.Symbol;
CompanyName=headline.CompanyName;
Entry=headline.Entry;
Modified=headline.Modified;
Source=headline.Source;
}
public Headline(String symbol,DateTime date,String entry)
{
Symbol=symbol;
Date=date;
Entry=entry;
Modified=DateTime.Now;
}
public DateTime Date{get;set;}
public String Symbol{get;set;}
public String CompanyName{get;set;}
public String Entry{get;set;}
public DateTime Modified{get;set;}
public String Source{get;set;}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using MarketData.Generator;
namespace MarketData.MarketDataModel
{
// These are models that were designed to be consumed by the mobile platform
public class PortfolioTradesWithParityPrice
{
public PortfolioTradesWithParityPrice(PortfolioTrades portfolioTrades, Price parityPrice)
{
Trades = portfolioTrades;
ParityPrice = parityPrice;
}
public Price ParityPrice { get; set; }
public PortfolioTrades Trades { get; set; }
}
// ************************************************************************************
public class GainLossSummaryItemDetail: GainLossSummaryItem
{
public GainLossSummaryItemDetail()
{
}
public GainLossSummaryItemDetail(GainLossSummaryItem gainLossSummaryItem)
{
this.Date=gainLossSummaryItem.Date;
this.Symbol=gainLossSummaryItem.Symbol;
this.CompanyName=gainLossSummaryItem.CompanyName;
this.CurrentGainLoss=gainLossSummaryItem.CurrentGainLoss;
this.PreviousGainLoss=gainLossSummaryItem.PreviousGainLoss;
this.Change=gainLossSummaryItem.Change;
this.ChangePercent=gainLossSummaryItem.ChangePercent;
this.HasStopLimit = gainLossSummaryItem.HasStopLimit;
}
public int Lots{get;set;}
public double Shares{get;set;}
public double Exposure{get;set;}
public double DividendYield{get;set;} // decimal
public double AnnualDividend{get;set;} // amount
public ParityElement ParityElement{get;set;}
public String ParityElementDescription{get{return null==ParityElement?"":ParityElement.ToString();}}
public double AllTimeGainLossPercent{get;set;}
public double PercentDistanceFromAllTimeGainLossPercent{get;set;}
public Price LatestPrice{get;set;}
public double PriceChange{get;set;}
public bool HasStopLimit{get;set;}
}
}

View File

@@ -0,0 +1,96 @@
using System;
using System.Text;
using MarketData.Utils;
using MarketData.MarketDataModel;
namespace MarketData.MarketDataModel
{
public class ModelTrade
{
public enum TradeType { Buy, Sell };
private DateTime tradeDate;
private String symbol;
private int shares;
private double price;
private TradeType tradeType;
private int daysHeld;
private double gainLoss;
private double exposure;
private double returnOnPosition;
private String comment;
public ModelTrade()
{
}
public String Symbol
{
get { return symbol; }
set { symbol = value; }
}
public DateTime TradeDate
{
get { return tradeDate; }
set { tradeDate = value; }
}
public int Shares
{
get { return shares; }
set { shares = value; }
}
public double Price
{
get { return price; }
set { price = value; }
}
public int DaysHeld
{
get { return daysHeld; }
set { daysHeld = value; }
}
public double GainLoss
{
get { return gainLoss; }
set { gainLoss = value; }
}
public double Return
{
get { return returnOnPosition; }
set { returnOnPosition = value; }
}
public double Exposure
{
get { return exposure; }
set { exposure = value; }
}
public String Comment
{
get { return comment; }
set { comment = value; }
}
public ModelTrade.TradeType Type
{
get { return tradeType; }
set { tradeType = value; }
}
public static String Header
{
get
{
return "Date,Buy/Sell,Symbol,Shares,Price,Gain/Loss,Days Held,Comment";
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(Utility.DateTimeToStringMMSDDSYYYY(TradeDate)).Append(",");
sb.Append(tradeType.Equals(ModelTrade.TradeType.Sell) ? "Sell" : "Buy").Append(",");
sb.Append(Symbol).Append(",");
sb.Append(Shares).Append(",");
sb.Append("\"" + String.Format("{0:C}", price) + "\"").Append(",");
sb.Append("\"" + String.Format("{0:C}", gainLoss) + "\"").Append(",");
sb.Append(daysHeld).Append(",");
sb.Append("\"").Append(null!=comment?comment:"").Append("\"");
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MarketData.Utils;
namespace MarketData.MarketDataModel
{
public class ParityElement
{
public String Symbol { get; set; }
public DateTime PricingDate { get; set; }
public double ParityOffsetPrice { get; set; }
public double ParityOffsetPercent { get; set; } // This is not a percent it needs to be multiplied by 100 to be a percentage
public override String ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("Even @").Append(Utility.FormatCurrency(ParityOffsetPrice)).Append(" (").Append(ParityOffsetPercent > 0 ? "+" : "").Append(Utility.FormatPercent(ParityOffsetPercent)).Append(")");
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
//using MarketData.DataAccess;
namespace MarketData.MarketDataModel
{
public class Portfolio
{
private List<ModelTrade> trades = new List<ModelTrade>();
private bool openPosition = false;
private double availableCash;
private double initialCash;
public Portfolio(double initialCash)
{
this.initialCash = this.availableCash = initialCash;
}
public List<ModelTrade> Trades
{
get { return trades; }
set { trades = value; }
}
public double AvailableCash
{
get { return availableCash; }
set { availableCash = value; }
}
public double GetPortfolioReturn(Price priceOpenPosition)
{
return (GetPortfolioValue(priceOpenPosition)-initialCash)/initialCash;
}
// pass in latest price so we can price any open position
public double GetPortfolioValue(Price priceOpenPosition)
{
double cashValue = AvailableCash;
if (0 != trades.Count)
{
ModelTrade lastTrade = trades[trades.Count - 1];
if (lastTrade.Type.Equals(ModelTrade.TradeType.Buy)) cashValue += (lastTrade.Shares * priceOpenPosition.Close);
}
return cashValue;
}
public void Add(ModelTrade trade)
{
trades.Add(trade);
}
public ModelTrade GetLastTrade()
{
return trades[trades.Count - 1];
}
public bool HasOpenPosition
{
get { return openPosition; }
set { openPosition = value; }
}
public int GetTradeCount()
{
return trades.Count;
}
public double GetAverageGainLoss()
{
double totalGainLoss = 0;
for (int index = 0; index < trades.Count; index++)
{
totalGainLoss += trades[index].GainLoss;
}
return totalGainLoss / trades.Count;
}
public int GetAverageHoldingDays()
{
int totalHoldingDays = 0;
int numberOfSellTrades = 0;
for (int index = 0; index < trades.Count; index++)
{
ModelTrade trade = trades[index];
if (trade.Type == ModelTrade.TradeType.Sell)
{
totalHoldingDays += trades[index].DaysHeld;
numberOfSellTrades++;
}
}
return (numberOfSellTrades>0?totalHoldingDays / numberOfSellTrades:0);
}
public int GetMinHoldingDays()
{
int minHoldingDays = Int16.MaxValue;
for (int index = 0; index < trades.Count; index++)
{
ModelTrade trade = trades[index];
int holdingDays = trade.DaysHeld;
if (trade.Type == ModelTrade.TradeType.Sell && holdingDays < minHoldingDays) minHoldingDays = holdingDays;
}
return minHoldingDays;
}
public int GetMaxHoldingDays()
{
int maxHoldingDays =0;
for (int index = 0; index < trades.Count; index++)
{
ModelTrade trade = trades[index];
int holdingDays = trade.DaysHeld;
if (trade.Type==ModelTrade.TradeType.Sell && holdingDays > maxHoldingDays) maxHoldingDays = holdingDays;
}
return maxHoldingDays;
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MarketData.Utils;
namespace MarketData.MarketDataModel
{
public class PortfolioTrade
{
private int tradeId=-1;
private String symbol;
private DateTime tradeDate;
private double shares;
private double price;
private double commission;
private String buySell;
private String account;
private String status;
private double sellPrice=double.NaN;
private DateTime sellDate=Utility.Epoch;
public int TradeId
{
get {return tradeId ;}
set { tradeId = value; ;}
}
public String Symbol
{
get { return symbol; }
set { symbol = value; }
}
public DateTime TradeDate
{
get { return tradeDate; }
set { tradeDate = value; }
}
public double Shares
{
get { return shares; }
set { shares = value; }
}
public double Exposure()
{
return Price*Shares;
}
public String BuySell
{
get { return buySell; }
set { buySell = value; }
}
public String Status
{
get { return status; }
set { status = value; }
}
public bool IsOpen
{
get { return status.ToUpper().Equals("OPEN"); }
}
public bool IsClosed
{
get { return !IsOpen; }
}
public String Account
{
get { return account; }
set{account=value;}
}
public DateTime SellDate
{
get { return sellDate; }
set { sellDate = value; }
}
public double SellPrice
{
get { return sellPrice;}
set { sellPrice = value;}
}
public double Price
{
get { return price; }
set { price = value; }
}
public double Commission
{
get { return commission; }
set { commission = value; }
}
}
}

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MarketData.Utils;
namespace MarketData.MarketDataModel
{
public class Position
{
public String Symbol { get; set; }
public double Shares{get;set;}
public double Exposure { get; set; }
public double MarketValue { get; set; }
}
public class PortfolioTrades : List<PortfolioTrade>
{
public PortfolioTrades()
{
}
public PortfolioTrades(List<PortfolioTrade> trades)
{
if(null==trades)return;
for (int index = 0; index < trades.Count; index++) Add(trades[index]);
}
public List<String> Symbols
{
get
{
Dictionary<String, String> uniqueSymbols = new Dictionary<String, String>();
List<String> symbols = new List<String>();
foreach (PortfolioTrade portfolioTrade in this)
{
if (!uniqueSymbols.ContainsKey(portfolioTrade.Symbol)) uniqueSymbols.Add(portfolioTrade.Symbol, portfolioTrade.Symbol);
}
symbols = new List<String>(uniqueSymbols.Values);
symbols.Sort();
return symbols;
}
}
public List<Position> GetPositions(DateTime asOf)
{
List<Position> positions = new List<Position>();
List<String> symbols = Symbols;
foreach (String symbol in symbols) positions.Add(GetPosition(symbol, asOf));
return positions;
}
public Position GetPosition(String symbol,DateTime asof)
{
List<PortfolioTrade> portfolioTrades = new List<PortfolioTrade>();
for (int index = 0; index < Count; index++)
{
PortfolioTrade portfolioTrade = this[index];
if (!portfolioTrade.Symbol.Equals(symbol)) continue;
if (portfolioTrade.IsOpen && portfolioTrade.TradeDate<=asof) { portfolioTrades.Add(portfolioTrade); continue; }
if (portfolioTrade.IsClosed && portfolioTrade.SellDate > asof) { portfolioTrades.Add(portfolioTrade); continue; }
}
if (0 == portfolioTrades.Count) return null;
Position position = new Position();
position.Symbol = symbol;
position.Shares = portfolioTrades.Sum(x => x.Shares);
position.Exposure = portfolioTrades.Sum(x=>x.Shares*x.Price);
return position;
}
public double Exposure(){return this.Sum(x=>x.Exposure());}
public List<String> Accounts
{
get
{
Dictionary<String, String> uniqueAccounts = new Dictionary<String, String>();
List<String> accounts = new List<String>();
foreach (PortfolioTrade portfolioTrade in this)
{
if (!uniqueAccounts.ContainsKey(portfolioTrade.Account)) uniqueAccounts.Add(portfolioTrade.Account, portfolioTrade.Account);
}
accounts = new List<String>(uniqueAccounts.Values);
accounts.Sort();
return accounts;
}
}
public DateTime GetMinTradeDate()
{
DateTime minDate = Utility.Epoch;
minDate = (from portfolioTrade in this select portfolioTrade.TradeDate).Min();
return minDate;
}
public DateTime GetMinTradeDate(String symbol)
{
DateTime minDate=Utility.Epoch;
symbol=symbol.ToUpper();
minDate = (from portfolioTrade in this where portfolioTrade.Symbol.Equals(symbol) select portfolioTrade.TradeDate).Min();
return minDate;
}
// We just want the trades (open or closed) on or before the specified date. This will be used to run a cumulative gain/loss and return
public PortfolioTrades GetTradesOnOrBefore(DateTime date)
{
PortfolioTrades tradesOnOrBefore = new PortfolioTrades();
foreach (PortfolioTrade portfolioTrade in this)
{
if (date >= portfolioTrade.TradeDate) tradesOnOrBefore.Add(portfolioTrade);
}
return tradesOnOrBefore;
}
// This will remove trades that are status='CLOSED' and SELL_DATE=closingDate
// The user of this fucntion would be making the inference that a trade that closed on closingDate should not be seen as part of the holdings.
// For example. The assumption would be that trades that closed on closingDate would not be a part of the portfolio on closingDate
public PortfolioTrades RemoveClosedTradesWhereClosedOn(DateTime closingDate)
{
PortfolioTrades portfolioTrades;
List<PortfolioTrade> removeTrades = (from PortfolioTrade portfolioTrade in this where portfolioTrade.Status.Equals("CLOSED") && portfolioTrade.SellDate.Date.Equals(closingDate.Date) select portfolioTrade).ToList();
if (null != removeTrades && 0 != removeTrades.Count) portfolioTrades = new PortfolioTrades(this.Except(removeTrades).ToList());
else portfolioTrades = this;
return portfolioTrades;
}
public PortfolioTrades GetOpenTradesOn(DateTime date)
{
PortfolioTrades openTrades = new PortfolioTrades();
foreach (PortfolioTrade portfolioTrade in this)
{
if (Utility.Epoch.Equals(portfolioTrade.SellDate)) // No sell date so trade is open
{
if (date >= portfolioTrade.TradeDate) openTrades.Add(portfolioTrade);
}
else // sell date is not epoch so see if date is in between tradedate and selldate
{
if (date >= portfolioTrade.TradeDate && date < portfolioTrade.SellDate) openTrades.Add(portfolioTrade); // assume that if the sell date is equal to date then the position is closed
}
}
return openTrades;
}
public bool HasOpenPositions(String symbol)
{
int openTrades=(from PortfolioTrade portfolioTrade in this where portfolioTrade.Symbol.Equals(symbol) && portfolioTrade.IsOpen select portfolioTrade).Count();
return openTrades>0?true:false;
}
public bool HasOpenPositionsOn(String symbol,DateTime dateTime)
{
PortfolioTrades portfolioTrades=GetOpenTradesOn(dateTime);
int numTrades=(from PortfolioTrade portfolioTrade in portfolioTrades where portfolioTrade.Symbol.Equals(symbol) select portfolioTrade).Count();
return numTrades>0?true:false;
}
// This method relies on the fact that BreakoutTrades method in PortfolioDA.GetTradesSymbol() creates pairs of BUY and SELL legs with paired legs sharing the same TradeId.
// The open trades will show up with count==1 when we group them by TradeId
public PortfolioTrades GetOpenTrades()
{
if(0==Count)return new PortfolioTrades();
PortfolioTrades openTrades=new PortfolioTrades((from PortfolioTrade trade in this select trade).GroupBy(x=>x.TradeId).Where(grouping=>grouping.Count()==1).Select(grouping=>grouping.FirstOrDefault()).ToList());
return openTrades;
}
public PortfolioTrades FilterAccount(String account)
{
PortfolioTrades portfolioTrades = new PortfolioTrades();
foreach (PortfolioTrade portfolioTrade in this)
{
if (portfolioTrade.Account.Equals(account)) portfolioTrades.Add(portfolioTrade);
}
return portfolioTrades;
}
public PortfolioTrades FilterAccount(List<String> accounts)
{
PortfolioTrades portfolioTrades = new PortfolioTrades();
foreach (PortfolioTrade portfolioTrade in this)
{
if(accounts.Any(x=>x.Equals(portfolioTrade.Account)))portfolioTrades.Add(portfolioTrade);
}
return portfolioTrades;
}
public PortfolioTrades FilterSymbol(String symbol)
{
PortfolioTrades portfolioTrades = new PortfolioTrades();
foreach (PortfolioTrade portfolioTrade in this)
{
if (portfolioTrade.Symbol.Equals(symbol)) portfolioTrades.Add(portfolioTrade);
}
return portfolioTrades;
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
namespace MarketData.MarketDataModel
{
public class PositionWithDescription : MarketDataModel.Position
{
public PositionWithDescription()
{
}
public PositionWithDescription(MarketDataModel.Position position, String companyName, String description)
{
if (null == position || null == description) return;
this.Symbol = position.Symbol;
this.Shares = position.Shares;
this.MarketValue = position.MarketValue;
this.Exposure = position.Exposure;
this.Description = description;
this.CompanyName = companyName;
}
public String Description { get; set; }
public String CompanyName { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace MarketData.MarketDataModel
{
public class PremarketElement
{
public String Market { get; set; }
public double ChangePercent { get; set; }
public double ChangeValue { get; set; }
public DateTime Timestamp { get; set; }
}
public class PremarketElements:List<PremarketElement>
{
public PremarketElements()
{
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
namespace MarketData.MarketDataModel
{
public class PriceIndex
{
public String Code{get;set;}
public String Name{get;set;}
public double Value{get;set;}
public DateTime AsOf{get;set;}
public String Source{get;set;}
}
public class PriceIndices : List<PriceIndex>
{
public PriceIndices()
{
}
public PriceIndices(List<PriceIndex> priceIndices)
{
foreach(PriceIndex priceIndex in priceIndices)
{
Add(priceIndex);
}
}
}
}

View File

@@ -0,0 +1,448 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using MarketData.Utils;
using MarketData.Numerical;
//using MarketData.DataAccess;
namespace MarketData.MarketDataModel
{
public class PricesByDate : Dictionary<DateTime, Price>
{
private DateTime maxDate=Utility.Epoch;
private DateTime minDate=Utility.Epoch;
public PricesByDate()
{
}
public new void Add(DateTime key,Price price)
{
base.Add(key,price);
if(key>maxDate)maxDate=key;
else if(Utility.IsEpoch(minDate))minDate=key;
else if(key<minDate)minDate=key;
}
public DateTime MaxDate
{
get{return maxDate;}
}
public DateTime MinDate
{
get{return minDate;}
}
}
public class PriceComparerDesc : IComparer<Price>
{
public int Compare(Price p1, Price p2)
{
if (p1.Date < p2.Date) return -1;
else if (p1.Date > p2.Date) return 1;
return 0;
}
}
// Throughout the application it is assumed that these collections, when populated, be be in descending date order.
public class Prices : List<Price>
{
public Prices()
{
}
public Prices(Price[] prices)
{
foreach (Price price in prices) Add(price);
}
public Prices(List<Price> prices)
{
foreach(Price price in prices)Add(price);
}
public Prices(String strCSV,String symbol)
{
String[] csvLines = strCSV.Split('\n');
Clear();
for (int index = 1; index < csvLines.Length; index++)
{
if (csvLines[index].Length < 1) continue;
String[] lineItems = csvLines[index].Split(',');
Price price = new Price();
String[] dateParts = lineItems[0].Split('-');
try { price.Date = new DateTime(int.Parse(dateParts[0]), int.Parse(dateParts[1]), int.Parse(dateParts[2])); }
catch (Exception /*exception*/)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("'{0}' does not contain a date", lineItems[0]));
continue;
}
price.Symbol = symbol;
price.Open = Double.Parse(lineItems[1]);
price.High = Double.Parse(lineItems[2]);
price.Low = Double.Parse(lineItems[3]);
price.Close = Double.Parse(lineItems[4]);
price.Volume = Int64.Parse(lineItems[5]);
if(lineItems.Length>6)price.AdjClose=Double.Parse(lineItems[6]);
Add(price);
}
}
// This Beta differs wildly with Yahoo Finance. Yahoo finance uses 36 buckets of monthly returns which was simulated when building this Investopedia-based routine.
// I have yet to discover the cause of the difference but I leave this routine in place as a matter of further study and to make comparisons.
// I tested the bucket methodology against just using a stream of returns and they produce the same result so this routine simply uses a stream of returns.
// At any rate, the beta produced by this method does not match to Yahoo finance.
//public double Beta(Prices bmkPrices)
//{
// double beta=double.NaN;
// if(Count!=bmkPrices.Count)return beta;
// float[] cumReturnsPricesArray=GetReturns();
// float[] cumReturnsPricesBenchmark=bmkPrices.GetReturns();
// beta=Numerics.Beta(ref cumReturnsPricesArray,ref cumReturnsPricesBenchmark);
// return beta*10;
//}
// Assumes that the prices are stored lowest date first
public double MaxDrawdown()
{
return Numerics.MaxDrawdown(GetPrices());
}
public double MaxUpside()
{
return Numerics.MaxUpside(GetPrices());
}
public PricesByDate GetPricesByDate()
{
PricesByDate pricesByDate = new PricesByDate();
for (int index = 0; index < Count; index++) pricesByDate.Add(this[index].Date, this[index]);
return pricesByDate;
}
public Prices Top(int count)
{
Prices prices = new Prices();
for (int index = 0; index < count && index<Count; index++)
{
prices.Add(this[index]);
}
return prices;
}
public Prices Bottom(int count)
{
Prices prices = new Prices();
for (int index = Count-1; index>=0 && prices.Count<count; index--)
{
prices.Add(this[index]);
}
return prices;
}
public double Volatility()
{
float[] pricesAr = GetPrices();
return Numerics.StdDev(ref pricesAr);
}
public double Min()
{
float[] pricesAr = GetPrices();
return Numerics.Min(ref pricesAr);
}
public double MinLow()
{
float[] pricesAr = GetPricesLow();
return Numerics.Min(ref pricesAr);
}
public double Max()
{
float[] pricesAr = GetPrices();
return Numerics.Max(ref pricesAr);
}
public double Mean()
{
float[] pricesAr = GetPrices();
return Numerics.Mean(ref pricesAr);
}
public double[] GetLeastSquaresFit()
{
double[] pricesArray = new double[Count];
for (int index = 0; index < Count; index++)
{
pricesArray[index] = (float)this[index].Close;
}
LeastSquaresResult leastSquaresResult=Numerics.LeastSquares(pricesArray);
return leastSquaresResult.LeastSquares;
}
public double[] GetVolume()
{
double[] volumeArray = new double[Count];
for (int index = 0; index < Count; index++)
{
volumeArray[index] = (double)this[index].Volume;
}
return volumeArray;
}
public float[] GetPrices()
{
float[] pricesArray = new float[Count];
for (int index = 0; index < Count; index++)
{
pricesArray[index] = (float)this[index].Close;
}
return pricesArray;
}
public float[] GetPricesLow()
{
float[] pricesArray = new float[Count];
for (int index = 0; index < Count; index++)
{
pricesArray[index] = (float)this[index].Low;
}
return pricesArray;
}
public float[] GetPricesHigh()
{
float[] pricesArray = new float[Count];
for (int index = 0; index < Count; index++)
{
pricesArray[index] = (float)this[index].High;
}
return pricesArray;
}
public float[] GetPrices(int startIndex, int count)
{
if (startIndex + count > Count) return null;
float[] pricesArray=new float[count];
for (int index = startIndex,arrayIndex=0; index < startIndex + count; index++,arrayIndex++)
{
pricesArray[arrayIndex] = (float)this[index].Close;
}
return pricesArray;
}
public float[] GetPricesHigh(int startIndex, int count)
{
if (startIndex + count > Count) return null;
float[] pricesArray = new float[count];
for (int index = startIndex, arrayIndex = 0; index < startIndex + count; index++, arrayIndex++)
{
pricesArray[arrayIndex] = (float)this[index].High;
}
return pricesArray;
}
public float[] GetPricesLow(int startIndex, int count)
{
if (startIndex + count > Count) return null;
float[] pricesArray = new float[count];
for (int index = startIndex, arrayIndex = 0; index < startIndex + count; index++, arrayIndex++)
{
pricesArray[arrayIndex] = (float)this[index].Low;
}
return pricesArray;
}
public float[] GetReturns()
{
if(Count==0||1==Count)return null;
float[] returns = new float[Count - 1];
for (int index = 0; index < Count - 1; index++)
{
Price currentPrice = this[index];
Price prevPrice = this[index + 1];
if (0.00 == prevPrice.Close) returns[index] = 0.00F;
else returns[index] = (float)((currentPrice.Close - prevPrice.Close) / Math.Abs(prevPrice.Close));
}
return returns;
}
public double GetReturn1D()
{
if(Count<2)return double.NaN;
Prices pricesForReturn1D=new Prices(this.Take(2).ToList());
return pricesForReturn1D.GetCumulativeReturn();
}
public float[] GetReturns(int dayCount)
{
if(Count-dayCount<=0)return new float[0];
float[] returns = new float[Count - dayCount];
for (int index = 0; index < Count - dayCount; index++)
{
Price currentPrice = this[index];
Price prevPrice = this[index + dayCount];
if (0.00 == prevPrice.Close) returns[index] = 0.00F;
else returns[index] = (float)((currentPrice.Close - prevPrice.Close) / Math.Abs(prevPrice.Close));
}
return returns;
}
public double GetCumulativeReturn()
{
float[] returns=GetReturns();
if(null==returns)return double.NaN;
double itemReturn=0.00;
for(int index=0;index<returns.Length;index++)itemReturn+=(double)returns[index];
return itemReturn;
}
public double GetCumulativeReturn(int dayCount)
{
float[] returns=GetReturns(dayCount);
double itemReturn=0.00;
for(int index=0;index<returns.Length;index++)itemReturn+=(double)returns[index];
return itemReturn;
}
public double[] GetReturnsAsDoubleArray()
{
double[] returns = new double[Count - 1];
for (int index = 0; index < Count - 1; index++)
{
Price currentPrice = this[index];
Price prevPrice = this[index + 1];
if (0.00 == prevPrice.Close) returns[index] = 0.00;
else returns[index] = (double)((currentPrice.Close - prevPrice.Close) / Math.Abs(prevPrice.Close));
}
return returns;
}
public double[] GetReturnsAsDoubleArray(int dayCount)
{
if (0 == Count) return null;
double[] returns = new double[Count - dayCount];
for (int index = 0; index < Count - dayCount; index++)
{
Price currentPrice = this[index];
Price prevPrice = this[index + dayCount];
if (0.00 == prevPrice.Close) returns[index] = 0.00F;
else returns[index] = ((currentPrice.Close - prevPrice.Close) / Math.Abs(prevPrice.Close));
}
return returns;
}
// *********************************
//public static Prices GetMonthlyPrices(String symbol, DateTime asof, int months = 36)
//{
// DateGenerator dateGenerator = new DateGenerator();
// Prices prices = new Prices();
// DateTime startDate = dateGenerator.GetCurrMonthStart(asof);
// DateTime minPricingDate = PricingDA.GetEarliestDate(symbol);
// Dictionary<DateTime, Price> symbolPricesByDate = new Dictionary<DateTime, Price>();
// List<DateTime> historicalDates = new List<DateTime>();
// while (historicalDates.Count < (months + 1))
// {
// historicalDates.Add(startDate);
// startDate = dateGenerator.GetPrevMonthStart(startDate);
// }
// DateTime requestStartDate = dateGenerator.DaysAddActual(asof, 5); // advance 5 days to provide an error margin for holidays
// Prices symbolPrices = PricingDA.GetPrices(symbol, requestStartDate, historicalDates[historicalDates.Count - 1]);
// foreach (Price price in symbolPrices) symbolPricesByDate.Add(price.Date, price);
// startDate = dateGenerator.GetCurrMonthStart(asof);
// while (prices.Count < (months + 1))
// {
// Price price = GetPrice(symbol, startDate, symbolPricesByDate);
// if (null == price) return null;
// prices.Add(price);
// startDate = dateGenerator.GetPrevMonthStart(startDate);
// if (startDate < minPricingDate) break;
// }
// return prices;
//}
private static Price GetPrice(String symbol,DateTime requestedDate, Dictionary<DateTime, Price> symbolPricesByDate)
{
int maxAdvanceDays = 5;
Price symbolPrice = null;
for (int advanceDays = 0; advanceDays < maxAdvanceDays; advanceDays++)
{
if (!symbolPricesByDate.ContainsKey(requestedDate)) { requestedDate = requestedDate.AddDays(1); continue; }
symbolPrice = symbolPricesByDate[requestedDate];
}
return symbolPrice;
}
// **********************************
}
public class Price
{
private String symbol;
private DateTime date;
private double open;
private double high;
private double low;
private double close;
private long volume;
private double adjClose;
public Price()
{
}
public Price Clone()
{
Price clonePrice=new Price();
clonePrice.Symbol=Symbol;
clonePrice.Date=Date;
clonePrice.Open=Open;
clonePrice.High=High;
clonePrice.Low=Low;
clonePrice.Close=Close;
clonePrice.Volume=Volume;
clonePrice.AdjClose=AdjClose;
return clonePrice;
}
public String Symbol
{
get { return symbol; }
set { symbol = value; }
}
public DateTime Date
{
get { return date; }
set { date = value; }
}
public double Open
{
get { return open; }
set { open = value; }
}
public double High
{
get { return high; }
set { high = value; }
}
public double Low
{
get { return low; }
set { low = value; }
}
public double Close
{
get { return close; }
set { close = value; }
}
public long Volume
{
get { return volume; }
set { volume = value; }
}
public double AdjClose
{
get { return adjClose; }
set { adjClose = value; }
}
public bool IsValid
{
get
{
if(null==symbol)return false;
if(Utility.IsEpoch(date))return false;
if(double.IsNaN(open))return false;
if(double.IsNaN(high))return false;
if(double.IsNaN(low))return false;
if(double.IsNaN(close))return false;
if(double.IsNaN(adjClose))return false;
return true;
}
}
public static String Header
{
get { return "Date,Symbol,Open,High,Low,Close,Volume,Adj Close"; } // ,M12,M26,MACD,Signal,Histogram
}
public override String ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(symbol).Append(",");
sb.Append(Utility.DateTimeToStringMMSDDSYYYY(Date)).Append(",");
sb.Append(String.Format("{0:0.00}", Open)).Append(",");
sb.Append(String.Format("{0:0.00}", High)).Append(",");
sb.Append(String.Format("{0:0.00}", Low)).Append(",");
sb.Append(String.Format("{0:0.00}", Close)).Append(",");
sb.Append(Volume).Append(",");
sb.Append(String.Format("{0:0.00}", AdjClose));
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
namespace MarketData.MarketDataModel
{
public class StopLimit
{
public String Symbol{get;set;}
public double StopPrice{get;set;}
public double Shares{get;set;}
public String StopType{get;set;}
public int Active{get;set;}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Linq;
using System.Collections.Generic;
using MarketData.Numerical;
namespace MarketData.MarketDataModel
{
public class TimeSeriesCollection : List<TimeSeriesElement>
{
public TimeSeriesCollection()
{
}
public TimeSeriesCollection(List<TimeSeriesElement> elements)
{
if (null == elements) return;
foreach (TimeSeriesElement element in elements) Add(element);
}
// Returns the intersection of both sets on the common dates
public static AlignDatesResult AlignDates(TimeSeriesCollection tsA,TimeSeriesCollection tsB)
{
List<DateTime> tsADates=(from ts in tsA select ts.AsOf).ToList();
List<DateTime> tsBDates=(from ts in tsB select ts.AsOf).ToList();
List<DateTime> tsIntersect=tsADates.Intersect(tsBDates).Distinct().ToList();
tsA=new TimeSeriesCollection((from ts in tsA where tsIntersect.Any(x=>x.Equals(ts.AsOf)) select ts).ToList());
tsB=new TimeSeriesCollection((from ts in tsB where tsIntersect.Any(x=>x.Equals(ts.AsOf)) select ts).ToList());
return new AlignDatesResult(tsA,tsB);
}
public float[] ToFloat()
{
float[] values = new float[Count];
for (int index = 0; index < Count; index++) values[index] = (float)this[index].Value;
return values;
}
public bool ContainsNegativeValues()
{
int count= (from TimeSeriesElement element in this where element.Value < 0 select element).Count();
return count > 0 ? true : false;
}
public TimeSeriesCollection RemoveNegativeValues()
{
return new TimeSeriesCollection((from TimeSeriesElement element in this where element.Value >= 0 select element).ToList());
}
// Removes the outliers from the collection. If the resulting collection contains zero elements then returns the original collection.
//public TimeSeriesCollection RemoveOutliers(int standardDeviations=4)
//{
// double[] values = (from TimeSeriesElement element in this select element.Value).ToArray();
// double valuesStd=Numerics.Volatility(ref values)*standardDeviations;
// TimeSeriesCollection timeSeriesCollection=new TimeSeriesCollection((from TimeSeriesElement element in this where element.Value <=valuesStd select element).ToList());
// if(0==timeSeriesCollection.Count)return this;
// else return timeSeriesCollection;
//}
}
public class TimeSeriesElement
{
public enum ElementType { INVALID, OTHER,BVPS, EPS, OperatingCashflow,FreeCashflow,Revenue,QuarterlyRevenue,Inventory,QuarterlyInventory,ROIC,OperatingIncome,WorkingCapital,ROA,NetIncomeAvailableToCommonShareholders,TaxRate,InterestExpense,COGS};
private String symbol;
private DateTime asof;
private ElementType elementType;
private double value;
private String otherType;
public TimeSeriesElement()
{
}
public String Symbol
{
get { return symbol; }
set { symbol = value; }
}
public DateTime AsOf
{
get { return asof; }
set { asof = value; }
}
public double Value
{
get { return value; }
set { this.value = value; }
}
public String OtherType
{
get{return otherType;}
set{otherType=value;}
}
public TimeSeriesElement.ElementType Type
{
get { return elementType; }
set { elementType = value; }
}
public static String StringForType(TimeSeriesElement.ElementType type)
{
switch (type)
{
case ElementType.INVALID :
return "???";
case ElementType.BVPS:
return "bvps";
case ElementType.EPS:
return "eps";
case ElementType.OperatingCashflow :
return "operating_cashflow";
case ElementType.FreeCashflow:
return "free_cashflow";
case ElementType.Revenue:
return "revenue";
case ElementType.QuarterlyRevenue:
return "quarterly_revenue";
case ElementType.OperatingIncome:
return "operating_income";
case ElementType.ROIC:
return "roic";
case ElementType.WorkingCapital:
return "working_capital";
case ElementType.ROA:
return "roa";
case ElementType.TaxRate :
return "tax_rate";
case ElementType.InterestExpense:
return "interest_expense";
case ElementType.NetIncomeAvailableToCommonShareholders:
return "net_income_available_to_common_shareholders";
case ElementType.COGS:
return "cogs";
default:
return "???";
}
}
}
public class AlignDatesResult
{
public AlignDatesResult()
{
}
public AlignDatesResult(TimeSeriesCollection collectionA,TimeSeriesCollection collectionB)
{
CollectionA=collectionA;
CollectionB=collectionB;
}
public TimeSeriesCollection CollectionA{get;set;}
public TimeSeriesCollection CollectionB{get;set;}
}
}

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using MarketData.DataAccess;
using MarketData.MarketDataModel;
using MarketData.Utils;
// This Beta calculator is modelled after Yahoo Finance Beta calculator. It calculates Beta using 36 monthly prices start at beginning of previous month and going back 36 months
// While the calculator does not match exactly to Yahoo Finance I will use this as an alternative in the event that Yahoo Finance Beta is no longer available.
namespace MarketData.Numerical
{
public class BetaPrices : List<BetaPrice>
{
public BetaPrices()
{
}
// assuming that the list is in descending date order
public double[] ReturnsBenchmark()
{
double[] returns=new double[Count-1];
for(int index=Count-2;index>=0;index--)
{
if(this[index+1].PriceBenchmark.Close==0.00)returns[index]=0.00;
else returns[index]=(this[index].PriceBenchmark.Close-this[index+1].PriceBenchmark.Close)/this[index+1].PriceBenchmark.Close;
}
return returns;
}
public double[] ReturnsSymbol()
{
double[] returns=new double[Count-1];
for(int index=Count-2;index>=0;index--)
{
if(this[index+1].PriceSymbol.Close==0.00)returns[index]=0.00;
else returns[index]=(this[index].PriceSymbol.Close-this[index+1].PriceSymbol.Close)/this[index+1].PriceSymbol.Close;
}
return returns;
}
}
public class BetaPrice
{
public BetaPrice(String symbol,String benchmark,Price symbolPrice,Price benchmarkPrice,DateTime pricingDate)
{
Symbol=symbol;
Benchmark=benchmark;
PricingDate=pricingDate;
PriceSymbol=symbolPrice;
PriceBenchmark=benchmarkPrice;
}
public DateTime PricingDate{get;set;}
public String Symbol{get;set;}
public String Benchmark{get;set;}
public Price PriceSymbol{get;set;}
public Price PriceBenchmark{get;set;}
}
public class BetaGenerator
{
private BetaGenerator()
{
}
//public static double Beta(String symbol,int months = 36)
//{
// return Beta(symbol, PricingDA.GetLatestDate(symbol), months);
//}
//public static double Beta(String symbol,DateTime asof,int months=36)
//{
// try
// {
// String benchmark = "SPY";
// DateGenerator dateGenerator = new DateGenerator();
// BetaPrices betaPrices = new BetaPrices();
// DateTime startDate = dateGenerator.GetPrevMonthStart(asof);
// DateTime minPricingDate = PricingDA.GetEarliestDate(symbol);
// Dictionary<DateTime, Price> symbolPricesByDate = new Dictionary<DateTime, Price>();
// Dictionary<DateTime, Price> benchmarkPricesByDate = new Dictionary<DateTime, Price>();
// List<DateTime> historicalDates = new List<DateTime>();
// while (historicalDates.Count < (months + 1))
// {
// historicalDates.Add(startDate);
// startDate = dateGenerator.GetPrevMonthStart(startDate);
// }
// Prices symbolPrices = PricingDA.GetPrices(symbol, asof, historicalDates[historicalDates.Count - 1]);
// Prices benchmarkPrices = PricingDA.GetPrices(benchmark, asof, historicalDates[historicalDates.Count - 1]);
// foreach (Price price in symbolPrices) symbolPricesByDate.Add(price.Date, price);
// foreach (Price price in benchmarkPrices) benchmarkPricesByDate.Add(price.Date, price);
// startDate = dateGenerator.GetPrevMonthStart(asof);
// while (betaPrices.Count < (months + 1))
// {
// BetaPrice betaPrice = GetPrice(symbol, benchmark, startDate, symbolPricesByDate, benchmarkPricesByDate);
// if (null == betaPrice)
// {
// return double.NaN;
// }
// betaPrices.Add(betaPrice);
// startDate = dateGenerator.GetPrevMonthStart(startDate);
// if (startDate < minPricingDate) break;
// }
// double[] returnsSymbol = betaPrices.ReturnsSymbol();
// double[] returnsBenchmark = betaPrices.ReturnsBenchmark();
// double beta = Numerics.Beta(ref returnsSymbol, ref returnsBenchmark);
// return beta;
// }
// catch (Exception exception)
// {
// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
// return double.NaN;
// }
//}
private static BetaPrice GetPrice(String symbol, String benchmark, DateTime requestedDate, Dictionary<DateTime, Price> symbolPricesByDate, Dictionary<DateTime, Price> benchmarkPricesByDate)
{
try
{
int maxAdvanceDays = 10;
Price symbolPrice = null;
Price benchmarkPrice = null;
for (int advanceDays = 0; advanceDays < maxAdvanceDays; advanceDays++)
{
if (!symbolPricesByDate.ContainsKey(requestedDate)) { requestedDate = requestedDate.AddDays(1); continue; }
symbolPrice = symbolPricesByDate[requestedDate];
if (!benchmarkPricesByDate.ContainsKey(requestedDate)) { requestedDate = requestedDate.AddDays(1); continue; }
benchmarkPrice = benchmarkPricesByDate[requestedDate];
}
if (null == symbolPrice || null == benchmarkPrice) return null;
symbolPrice.Date = requestedDate.Date;
benchmarkPrice.Date = requestedDate.Date;
return new BetaPrice(symbol, benchmark, symbolPrice, benchmarkPrice, requestedDate);
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
return null;
}
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MarketData.Numerical
{
public interface IBinValueExtractor
{
double BinValue();
}
public class BinCollection<T> : List<BinItems<T>>
{
}
public class BinItems<T> : List<T>
{
public BinItems()
{
}
public BinItems(List<T> list)
{
foreach(T item in list)Add(item);
}
}
public class BinHelper<T> where T : IBinValueExtractor
{
public static BinCollection<T> CreateBins(BinItems<T> items,int bins)
{
BinCollection<T> binCollection=new BinCollection<T>();
if(null==items||0==items.Count)
{
for(int index=0;index<bins;index++)binCollection.Add(new BinItems<T>());
return binCollection;
}
items.Sort();
T minItem=items[0];
T maxItem=items[items.Count-1];
double midPoint=(maxItem.BinValue()-minItem.BinValue())/(double)bins;
List<double> borderValues=new List<double>();
for(int index=0;index<bins+1;index++)
{
if(0==index){borderValues.Add(minItem.BinValue());continue;}
else if(index==bins)borderValues.Add(borderValues[index-1]+midPoint+1);
else borderValues.Add(borderValues[index-1]+midPoint);
}
binCollection.Add(new BinItems<T>());
for(int index=0;index<borderValues.Count;index++)
{
double lowerBound;
double upperBound;
BinItems<T> binItems=binCollection[binCollection.Count-1];
lowerBound=borderValues[index];
if(index==borderValues.Count-1)upperBound=maxItem.BinValue();
else upperBound=borderValues[index+1];
for(int itemIndex=0;itemIndex<items.Count;itemIndex++)
{
T item=items[itemIndex];
if(item.BinValue()>=lowerBound&&item.BinValue()<upperBound)binItems.Add(item);
}
if(index<borderValues.Count-2)binCollection.Add(new BinItems<T>());
}
return binCollection;
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using MarketData.MarketDataModel;
namespace MarketData.Numerical
{
/// <summary>
/// Black Sholes Option Pricing Model for simplest scenario
/// </summary>
public class BlackScholesOptionPricingModel
{
private BlackScholesOptionPricingModel()
{
}
/// <summary>
/// Get Option price by applying BlackScholesOptionPricingModel
/// </summary>
/// <param name="optionType">Enum to indicate whether Call or Put</param>
/// <param name="S">Price of underlying</param>
/// <param name="X">Strike price</param>
/// <param name="T">Time to expiration in years</param>
/// <param name="r">Risk free interest rate</param>
/// <param name="v">Volatility</param>
/// <returns></returns>
//public static double GetPrice(OptionTypeEnum optionType, double S, double X, double T, double r, double v)
//{
// double d1 = 0.0;
// double d2 = 0.0;
// double optionValue = 0.0;
// d1 = (Math.Log(S / X) + (r + v * v / 2.0) * T) / (v * Math.Sqrt(T));
// d2 = d1 - v * Math.Sqrt(T);
// if (optionType == OptionTypeEnum.CallOption)
// {
// optionValue = S * CumulativeNormalDistributionFun(d1) - X * Math.Exp(-r * T) * CumulativeNormalDistributionFun(d2);
// }
// else if (optionType == OptionTypeEnum.PutOption)
// {
// optionValue = X * Math.Exp(-r * T) * CumulativeNormalDistributionFun(-d2) - S * CumulativeNormalDistributionFun(-d1);
// }
// return optionValue;
//}
/// <summary>
/// Cumulative normal distribution function
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
private static double CumulativeNormalDistributionFun(double d)
{
double L = 0.0;
double K = 0.0;
double dCND = 0.0;
const double a1 = 0.31938153;
const double a2 = -0.356563782;
const double a3 = 1.781477937;
const double a4 = -1.821255978;
const double a5 = 1.330274429;
L = Math.Abs(d);
K = 1.0 / (1.0 + 0.2316419 * L);
dCND = 1.0 - 1.0 / Math.Sqrt(2 * Convert.ToDouble(Math.PI)) * Math.Exp(-L * L / 2.0) * (a1 * K + a2 * K * K + a3 * Math.Pow(K, 3.0) + a4 * Math.Pow(K, 4.0) + a5 * Math.Pow(K, 5.0));
if (d < 0)
{
return 1.0 - dCND;
}
else
{
return dCND;
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections;
//using System.Data.SqlClient;
using System.Text;
using System.IO;
// Filename: KSTest.cs
// Author:Yan Kvitko
// Date:01/2005
namespace MarketData.Numerical
{
[Serializable]
public class KSTest
{
private int h;
private double pValue;
private double ksStat;
private double criticalValue;
public KSTest()
{
}
public KSTest(int h, double pValue, double ksStat, double criticalValue)
{
this.h=h;
this.pValue=pValue;
this.ksStat=ksStat;
this.criticalValue=criticalValue;
}
public int H
{
get{return h;}
set{h=value;}
}
public double PValue
{
get{return pValue;}
set{pValue=value;}
}
public double KSStat
{
get{return ksStat;}
set{ksStat=value;}
}
public double CriticalValue
{
get{return criticalValue;}
set{criticalValue=value;}
}
}
}

View File

@@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MarketData.Utils;
namespace MarketData.Numerical
{
public class LeastSquaresResult
{
public double[] LeastSquares { get; set; }
public double YIntercept { get; set; }
public double XIntercept { get; set; }
public double Slope { get; set; }
public void Extend(int itemCount, double slope) // extend the result set by itemCount by applying the slope to subsequent values
{
if (null == LeastSquares || 0 == LeastSquares.Length) return;
double[] extendedItems = new double[itemCount + LeastSquares.Length];
Array.Copy(LeastSquares, 0, extendedItems, itemCount, LeastSquares.Length);
for (int index = itemCount - 1; index >= 0; index--)
{
extendedItems[index] = extendedItems[index + 1] + slope;
}
LeastSquares = extendedItems;
}
}
public class LeastSquaresResultWithR2 : LeastSquaresResult
{
public double RSquared { get; set; }
}
// **********************************************************************************************************************************************
public class LeastSquaresHelper
{
private LeastSquaresHelper()
{
}
// This version reverses the slope because the input data is in reverse order
// The input data should be in the following manner observations[count-1]=earliest data point, observations[0]=most recent data point
// This version should be retained as-is because it is being referenced in models etc.,
public static LeastSquaresResult CalculateLeastSquares(double[] observations)
{
try
{
LeastSquaresResult leastSquaresResult = new LeastSquaresResult();
double[] xSeries = new double[observations.Length];
double[] xMinusXMean = new double[observations.Length];
double[] yMinusYMean = new double[observations.Length];
double[] meanProduct = new double[observations.Length];
double[] xMinusXMeanSquared = new double[observations.Length];
double[] leastSquares = new double[observations.Length];
double xMean = double.NaN;
double yMean = double.NaN;
double slope = double.NaN;
double yIntercept = double.NaN;
for (int index = 0; index < xSeries.Length; index++) xSeries[index] = index + 1;
xMean = Numerics.Mean(ref xSeries);
yMean = Numerics.Mean(ref observations);
for (int index = 0; index < observations.Length; index++)
{
xMinusXMean[index] = xSeries[index] - xMean;
yMinusYMean[index] = observations[index] - yMean;
meanProduct[index] = xMinusXMean[index] * yMinusYMean[index];
xMinusXMeanSquared[index] = xMinusXMean[index] * xMinusXMean[index];
}
slope = Numerics.Sum(ref meanProduct) / Numerics.Sum(ref xMinusXMeanSquared);
yIntercept = Numerics.YIntercept(xMean, yMean, slope);
for (int index = 0; index < leastSquares.Length; index++) leastSquares[index] = slope * xSeries[index] + yIntercept;
leastSquaresResult.LeastSquares = leastSquares;
leastSquaresResult.YIntercept = yIntercept;
leastSquaresResult.XIntercept = xMean;
leastSquaresResult.Slope = slope * -1.00;
return leastSquaresResult;
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, exception.ToString());
return null;
}
}
// This version uses the true slope whereas the version above reverses the slope due to the arrangement of the input data
// The input data should be in the following manner observations[0]=earliest data point, observations[count-1]=most recent data point
public static LeastSquaresResultWithR2 CalculateLeastSquaresWithR2(double[] observations)
{
try
{
LeastSquaresResultWithR2 leastSquaresResultWithR2 = new LeastSquaresResultWithR2();
double[] xSeries = new double[observations.Length];
double[] xMinusXMean = new double[observations.Length];
double[] yMinusYMean = new double[observations.Length];
double[] meanProduct = new double[observations.Length];
double[] xMinusXMeanSquared = new double[observations.Length];
double[] leastSquares = new double[observations.Length];
double xMean = double.NaN;
double yMean = double.NaN;
double slope = double.NaN;
double yIntercept = double.NaN;
for (int index = 0; index < xSeries.Length; index++) xSeries[index] = index + 1;
xMean = Numerics.Mean(ref xSeries);
yMean = Numerics.Mean(ref observations);
for (int index = 0; index < observations.Length; index++)
{
xMinusXMean[index] = xSeries[index] - xMean;
yMinusYMean[index] = observations[index] - yMean;
meanProduct[index] = xMinusXMean[index] * yMinusYMean[index];
xMinusXMeanSquared[index] = xMinusXMean[index] * xMinusXMean[index];
}
slope = Numerics.Sum(ref meanProduct) / Numerics.Sum(ref xMinusXMeanSquared);
yIntercept = Numerics.YIntercept(xMean, yMean, slope);
for (int index = 0; index < leastSquares.Length; index++) leastSquares[index] = slope * xSeries[index] + yIntercept;
leastSquaresResultWithR2.LeastSquares = leastSquares;
leastSquaresResultWithR2.YIntercept = yIntercept;
leastSquaresResultWithR2.XIntercept = xMean;
leastSquaresResultWithR2.Slope = slope;
// calculate the R2
double[] estimated = new double[observations.Length];
double[] estimatedLessMeanSquared = new double[observations.Length];
double sumOfEstimatedLessMeanSquared = 0.00;
double sumofsquares = 0.00;
foreach (double observation in observations) sumofsquares += Math.Pow(observation - yMean, 2);
for (int index = 0; index < observations.Length; index++) estimated[index] = yIntercept + (slope * (index + 1));
for (int index = 0; index < observations.Length; index++) estimatedLessMeanSquared[index] = Math.Pow(estimated[index] - yMean, 2);
foreach (double value in estimatedLessMeanSquared) sumOfEstimatedLessMeanSquared += value;
leastSquaresResultWithR2.RSquared = sumOfEstimatedLessMeanSquared / sumofsquares;
return leastSquaresResultWithR2;
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG, exception.ToString());
return null;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections;
namespace MarketData.Numerical
{
// The column is the key, the row is the value.
// For Time series elements put the date in the column and the value in the row
public class Element
{
private double row;
private double column;
public Element()
{
}
public Element(double column, double row)
{
this.column = column;
this.row = row;
}
public double Row
{
get { return row; }
set { row = value; }
}
public double Column
{
get { return column; }
set { column = value; }
}
}
public class CatmullRom
{
private CatmullRom()
{
}
public static bool PerformSpline(Element[] sourcePairs, Element[] destPairs)
{
double a0, a1, a2, a3;
double dx, dx1, dx2;
double dy, dy1, dy2;
double endPointOne;
double endPointTwo;
double resamplingPos;
double xPoint;
int clampOne, clampTwo;
int direction;
int destSize = destPairs.Length;
int sourceSize = sourcePairs.Length;
int inputIndex, index;
a0 = a1 = a2 = a3 = endPointOne = 0;
if (sourceSize < 2 || destSize < 1) return false;
if (((Element)sourcePairs[0]).Column < ((Element)sourcePairs[1]).Column)
{
if (((Element)destPairs[0]).Column < ((Element)sourcePairs[0]).Column ||
((Element)destPairs[destSize - 1]).Column > ((Element)sourcePairs[sourceSize - 1]).Column)
direction = 0;
else direction = 1;
}
else
{
if (((Element)destPairs[0]).Column > ((Element)sourcePairs[0]).Column ||
((Element)destPairs[destSize - 1]).Column < ((Element)sourcePairs[sourceSize - 1]).Column)
direction = 0;
else direction = -1;
}
if (0 == direction) return false;
if (1 == direction) endPointTwo = ((Element)destPairs[0]).Column - 1;
else endPointTwo = ((Element)destPairs[0]).Column + 1;
for (index = 0; index < destSize; index++)
{
resamplingPos = ((Element)destPairs[index]).Column;
if ((1 == direction && resamplingPos > endPointTwo) ||
(-1 == direction && resamplingPos < endPointTwo))
{
for (inputIndex = 0; inputIndex < sourceSize && resamplingPos > ((Element)sourcePairs[inputIndex]).Column; inputIndex++) ;
if (resamplingPos < ((Element)sourcePairs[inputIndex]).Column) inputIndex--;
if (inputIndex < 0) inputIndex = 0;
else if (inputIndex == sourceSize-1) inputIndex--;
endPointOne = ((Element)sourcePairs[inputIndex]).Column;
endPointTwo = ((Element)sourcePairs[inputIndex + 1]).Column;
clampOne = Math.Max(inputIndex - 1, 0);
clampTwo = Math.Min(inputIndex + 2, sourceSize - 1);
double clampOneValue = ((Element)sourcePairs[clampOne]).Column;
double clampTwoValue = ((Element)sourcePairs[clampTwo]).Column;
dx = 1.0 / ((endPointTwo - endPointOne)==0?1:(endPointTwo-endPointOne));
dx1 = 1.0 / ((endPointTwo - clampOneValue) == 0 ? 1 : (endPointTwo - clampOneValue));
dx2 = 1.0 / (clampTwoValue-endPointOne == 0 ? 1 : (clampTwoValue - endPointOne));
dy = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx;
dy1 = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[clampOne]).Row) * dx1;
dy2 = (((Element)sourcePairs[clampTwo]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx2;
a0 = ((Element)sourcePairs[inputIndex]).Row;
a1 = dy1;
a2 = dx * (3 * dy - 2 * dy1 - dy2);
a3 = dx * dx * (-2 * dy + dy1 + dy2);
}
xPoint = resamplingPos - endPointOne;
((Element)destPairs[index]).Row = ((a3 * xPoint + a2) * xPoint + a1) * xPoint + a0;
}
return true;
}
public static Element[] CreateSplineSourceElements(double[] columns, double[] rows)
{
Element[] elements = new Element[columns.Length];
if (columns.Length != rows.Length) return null;
for (int index = 0; index < columns.Length; index++)
{
elements[index] = new Element(columns[index], rows[index]);
}
return elements;
}
}
} // namespace

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MarketData.Service
{
public class Authorizations
{
public static String Xor(String input, int magic=5)
{
StringBuilder sb = new StringBuilder();
foreach (char ch in input) sb.Append((char)(ch ^ (char)magic));
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,617 @@
using MarketData.MarketDataModel;
using MarketData.MarketDataModel.GainLoss;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web;
using Xamarin.Essentials;
namespace MarketData.Service
{
// http://192.168.0.73:8000
public class MarketDataServiceClient
{
private Uri baseUri = null;
private HttpClient httpClient = null;
private String accessToken = null;
private List<Exception> exceptions = new List<Exception>();
private static MarketDataServiceClient marketDataServiceClient=null;
private static readonly TimeSpan CONNECTION_TIMEOUT=new TimeSpan(0,0,60);
private MarketDataServiceClient()
{
}
public static MarketDataServiceClient GetInstance()
{
lock(typeof(MarketDataServiceClient))
{
if(null==marketDataServiceClient)
{
marketDataServiceClient=new MarketDataServiceClient();
}
return marketDataServiceClient;
}
}
public void SetUrl(String url,String user)
{
lock(this)
{
if(String.IsNullOrEmpty(url))return;
baseUri = new Uri(url);
httpClient = new HttpClient();
httpClient.BaseAddress = baseUri;
httpClient.Timeout=CONNECTION_TIMEOUT;
ServiceResult serviceResult=Login(user);
if(!serviceResult.Success)return;
accessToken=(String)serviceResult.ContextSpecificResult;
}
}
public String GetBaseUri()
{
return null==baseUri?"":baseUri.ToString();
}
public bool Ping(String url)
{
lock(this)
{
if(String.IsNullOrEmpty(url))return false;
HttpClient httpClient=new HttpClient();
try
{
httpClient.BaseAddress=new Uri(url);
httpClient=new HttpClient();
httpClient.BaseAddress=new Uri(url);
httpClient.Timeout=new TimeSpan(0,0,10);
bool result=false;
if(!IsNetworkAvailable())return false;
StringBuilder sb = new StringBuilder();
sb.Append("/api/Ping/GetPing");
String json = httpClient.GetStringAsync(sb.ToString()).Result;
result = JsonConvert.DeserializeObject<bool>(json);
return result;
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return false;
}
finally
{
if(null!=httpClient)
{
httpClient.Dispose();
httpClient=null;
}
}
}
}
private ServiceResult Login(String user)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
StringBuilder sb = new StringBuilder();
user = Authorizations.Xor(user);
sb.Append("/api/Authorization/GetToken?").Append("user=").Append(user);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
String accessToken = JsonConvert.DeserializeObject<String>(json);
return new ServiceResult(accessToken);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
// ********************************************************** C O N S U M E R P R I C E I N D E X *************************************************
public ServiceResult GetDistinctConsumerPriceIndices()
{
lock (this)
{
try
{
if (!IsNetworkAvailable()) return new ServiceResult(false, "No network.");
if (!IsAuthorized()) return new ServiceResult(false, "Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/PriceIndex/GetDistinctPriceIndices?").Append("token=").Append(accessToken);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<String> priceIndices = JsonConvert.DeserializeObject<List<String>>(json);
return new ServiceResult(priceIndices);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false, exception.ToString());
}
}
}
public ServiceResult GetGetConsumerPriceIndex(String indexCode)
{
lock (this)
{
try
{
if (!IsNetworkAvailable()) return new ServiceResult(false, "No network.");
if (!IsAuthorized()) return new ServiceResult(false, "Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/PriceIndex/GetConsumerPriceIndex?").Append("token=").Append(accessToken).Append("&").Append("indexCode=").Append(HttpUtility.UrlEncode(indexCode));
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<PriceIndex> priceIndices = JsonConvert.DeserializeObject<List<PriceIndex>>(json);
return new ServiceResult(priceIndices);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false, exception.ToString());
}
}
}
// ************************************************************************ P R E M A R K E T *************************************************
public ServiceResult GetLatestPremarketData(String market,DateTime marketDate)
{
lock (this)
{
try
{
if (!IsNetworkAvailable()) return new ServiceResult(false, "No network.");
if (!IsAuthorized()) return new ServiceResult(false, "Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/PreMarket/GetLatestPremarketData?").Append("token=").Append(accessToken).Append("&").Append("market=").Append(HttpUtility.UrlEncode(market));
sb.Append("&").Append("marketDate=").Append(marketDate);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<PremarketElement> premarketData = JsonConvert.DeserializeObject<List<PremarketElement>>(json);
return new ServiceResult(premarketData);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false, exception.ToString());
}
}
}
public ServiceResult GetAvailableMarkets()
{
lock (this)
{
try
{
if (!IsNetworkAvailable()) return new ServiceResult(false, "No network.");
if (!IsAuthorized()) return new ServiceResult(false, "Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/PreMarket/GetAvailableMarkets?").Append("token=").Append(accessToken);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<String> availableMarkets = JsonConvert.DeserializeObject<List<String>>(json);
return new ServiceResult(availableMarkets);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false, exception.ToString());
}
}
}
public ServiceResult GetAvailableMarketDates(String market)
{
lock (this)
{
try
{
if (!IsNetworkAvailable()) return new ServiceResult(false, "No network.");
if (!IsAuthorized()) return new ServiceResult(false, "Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/PreMarket/GetAvailableMarketDates?").Append("token=").Append(accessToken).Append("&").Append("market=").Append(HttpUtility.UrlEncode(market));
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<DateTime> availableMarketDates = JsonConvert.DeserializeObject<List<DateTime>>(json);
return new ServiceResult(availableMarketDates);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false, exception.ToString());
}
}
}
// ************************************************************************************************************************************************
public ServiceResult GetPortfolioTradesWithCombinedLots(String symbol)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Portfolio/GetPortfolioTradesWithCombinedLots?").Append("token=").Append(accessToken).Append("&").Append("symbol=").Append(symbol);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<PortfolioTrade> portfolioTrades= JsonConvert.DeserializeObject<List<PortfolioTrade>>(json);
return new ServiceResult(portfolioTrades);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetStopLimit(String symbol)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Portfolio/GetStopLimit?").Append("token=").Append(accessToken).Append("&").Append("symbol=").Append(symbol);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
if(null==json)return new ServiceResult(null);
StopLimit stopLimit= JsonConvert.DeserializeObject<StopLimit>(json);
return new ServiceResult(stopLimit);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetPortfolioTradesWithParityPrice(String symbol)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Portfolio/GetPortfolioTradesWithParityPrice?").Append("token=").Append(accessToken).Append("&").Append("symbol=").Append(symbol);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
PortfolioTradesWithParityPrice portfolioTradesWithParityPrice= JsonConvert.DeserializeObject<PortfolioTradesWithParityPrice>(json);
return new ServiceResult(portfolioTradesWithParityPrice);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetPositionsWithDescription()
{
lock (this)
{
try
{
if (!IsNetworkAvailable()) return new ServiceResult(false, "No network.");
if (!IsAuthorized()) return new ServiceResult(false, "Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Portfolio/GetOpenPositionsWithDescription?").Append("token=").Append(accessToken);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<PositionWithDescription> positionsWithDescription = JsonConvert.DeserializeObject<List<PositionWithDescription>>(json);
return new ServiceResult(positionsWithDescription);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false, exception.ToString());
}
}
}
public ServiceResult GetWatchList(String watchList)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/WatchList/GetWatchList?").Append("token=").Append(accessToken).Append("&").Append("watchList=").Append(watchList);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<String> symbols= JsonConvert.DeserializeObject<List<String>>(json);
return new ServiceResult(symbols);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetHeadlines(DateTime headlineDate)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Headlines/GetHeadlines?").Append("token=").Append(accessToken).Append("&").Append("headlineDate=").Append(headlineDate);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<Headline> headlines= JsonConvert.DeserializeObject<List<Headline>>(json);
return new ServiceResult(headlines);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetHeadlineDates()
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Headlines/GetHeadlineDates?").Append("token=").Append(accessToken);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<String> headlineDates= JsonConvert.DeserializeObject<List<String>>(json);
return new ServiceResult(headlineDates);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetLatestHeadlines()
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Headlines/GetLatestHeadlines?").Append("token=").Append(accessToken);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<Headline> latestHeadlines= JsonConvert.DeserializeObject<List<Headline>>(json);
return new ServiceResult(latestHeadlines);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetLatestPricingDate()
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Price/GetLatestPricingDate?").Append("token=").Append(accessToken);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
DateTime latestPricingDate= JsonConvert.DeserializeObject<DateTime>(json);
return new ServiceResult(latestPricingDate);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetGainLossDetails(DateTime selectedDate,String account)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/GainLoss/GetGainLossWithDetail?").Append("token=").Append(accessToken).Append("&selectedDate=").Append(selectedDate.ToShortDateString()).Append("&").Append("account=").Append(account);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<GainLossSummaryItemDetail> gainLossSummaryDetail = JsonConvert.DeserializeObject<List<GainLossSummaryItemDetail>>(json);
return new ServiceResult(gainLossSummaryDetail);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetGainLossDetails(DateTime selectedDate)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/GainLoss/GetGainLossWithDetail?").Append("token=").Append(accessToken).Append("&selectedDate=").Append(selectedDate.ToShortDateString());
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<GainLossSummaryItemDetail> gainLossSummaryDetail = JsonConvert.DeserializeObject<List<GainLossSummaryItemDetail>>(json);
return new ServiceResult(gainLossSummaryDetail);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetCompoundGainLoss(int selectedDays)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
bool includeDividends=false;
sb.Append("/api/GainLoss/GetCompoundGainLoss?").Append("token=").Append(accessToken).Append("&selectedDays=").Append(selectedDays).Append("&").Append("includeDividends=").Append(includeDividends);;
String json = httpClient.GetStringAsync(sb.ToString()).Result;
GainLossCompoundModelCollection gainLossCompoundModelCollection = JsonConvert.DeserializeObject<GainLossCompoundModelCollection>(json);
return new ServiceResult(gainLossCompoundModelCollection);
}
catch (Exception exception)
{
exceptions.Add(exception);
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetAccountsWithOpenTrades()
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized()) return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Portfolio/GetAccountsWithOpenTrades?").Append("token=").Append(accessToken);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<String> accounts = JsonConvert.DeserializeObject<List<String>>(json);
return new ServiceResult(accounts);
}
catch (Exception exception)
{
Debug.WriteLine(exception.ToString());
return null;
}
}
}
public ServiceResult GetPrices(String symbol, int days)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized())return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Price/GetPrices?").Append("token=").Append(accessToken).Append("&").Append("symbol=").Append(symbol).Append("&").Append("days=").Append(days);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<Price> prices = JsonConvert.DeserializeObject<List<Price>>(json);
return new ServiceResult(prices);
}
catch (Exception exception)
{
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetCompanyNameForSymbol(String symbol)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized())return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Price/GetCompanyNameForSymbol?").Append("token=").Append(accessToken).Append("&").Append("symbol=").Append(symbol);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
String companyName = JsonConvert.DeserializeObject<String>(json);
return new ServiceResult(companyName);
}
catch (Exception exception)
{
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public ServiceResult GetBollingerBands(String symbol,int dayCount)
{
lock(this)
{
try
{
if(!IsNetworkAvailable())return new ServiceResult(false,"No network.");
if (!IsAuthorized())return new ServiceResult(false,"Unauthorized.");
StringBuilder sb = new StringBuilder();
sb.Append("/api/Price/GetBollingerBands?").Append("token=").Append(accessToken).Append("&").Append("symbol=").Append(symbol).Append("&").Append("dayCount=").Append(dayCount);
String json = httpClient.GetStringAsync(sb.ToString()).Result;
List<BollingerBandElement> bollingerBands=JsonConvert.DeserializeObject<List<BollingerBandElement>>(json);
return new ServiceResult(bollingerBands);
}
catch (Exception exception)
{
Debug.WriteLine(exception.ToString());
return new ServiceResult(false,exception.ToString());
}
}
}
public bool IsAuthorized()
{
if (null == accessToken) return false;
return true;
}
public static bool IsNetworkAvailable()
{
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)return true;
return false;
}
public static bool IsWiFiNetwork()
{
if(!IsNetworkAvailable())return false;
if(Connectivity.ConnectionProfiles.Contains(ConnectionProfile.WiFi))return true;
return false;
}
}
}

View File

@@ -0,0 +1,32 @@
using MarketData.MarketDataModel;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Text;
namespace MarketData.Service
{
public class ServiceResult
{
public ServiceResult(bool success)
{
Success=success;
}
public ServiceResult(bool success,String message)
{
Success=success;
Message=message;
}
public ServiceResult(Object contextSpecificResult)
{
Success=true;
ContextSpecificResult=contextSpecificResult;
}
public bool Success{get;set;}
public Object ContextSpecificResult{get;set;}
public String Message{get;set;}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Text;
using System.Collections.Generic;
namespace MarketData.Utils
{
public class CSVLineHelper
{
public CSVLineHelper()
{
}
public static String[] ParseLine(String strLine)
{
try
{
List<String> items = new List<String>();
int length = strLine.Length;
for (int index = 0; index < length; index++)
{
char ch = strLine[index];
if (ch == '"') items.Add(GetQuotedItem(strLine, ref index, length));
else items.Add(GetItem(strLine, ref index, length));
}
return items.ToArray();
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
return null;
}
}
private static String GetQuotedItem(String strLine,ref int index,int length)
{
StringBuilder sb = new StringBuilder();
char ch = '\0';
while (index<length)
{
ch = strLine[++index];
if (ch == '"') { index++; break; }
if (ch != ',') sb.Append(ch);
}
return sb.ToString();
}
private static String GetItem(String strLine, ref int index, int length)
{
StringBuilder sb = new StringBuilder();
char ch='\0';
while (ch != ',' && index<length)
{
ch = strLine[index++];
if (ch != ',') sb.Append(ch);
}
index--;
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,344 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MarketData.Utils;
// Filename: DateGenerator.cs
// Author:Sean Kessler
namespace MarketData.Utils
{
/// <summary>DateGenerator - Generate Historical Dates</summary>
[Serializable]
public class DateGenerator
{
private Hashtable holidays=null;
public DateGenerator()
{
}
public DateTime GetPrevMonthStart(DateTime dateTime)
{
DateTime startDate = new DateTime(dateTime.Year, dateTime.Month, 1);
startDate = startDate.AddMonths(-1);
startDate = GetNextBusinessDay(startDate);
return startDate;
}
public DateTime GetCurrMonthStart(DateTime dateTime)
{
DateTime startDate = new DateTime(dateTime.Year, dateTime.Month, 1);
startDate = GetNextBusinessDay(startDate);
return startDate;
}
public DateGenerator(Hashtable holidays)
{
this.holidays=holidays;
}
public static int GetPrevMonth(int month)
{
if(1==month)return 12;
return month-1;
}
/// <summary>FindPrevBusinessDay - Finds previous business day</summary>
/// <returns>DateTime</returns>
public DateTime FindPrevBusinessDay(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(1,0,0,0);
asOf=asOf.Subtract(oneDay);
while(IsWeekend(asOf)||IsHoliday(asOf))asOf=asOf.Subtract(oneDay);
return asOf;
}
/// <summary>FindNextBusinessDays - Finds following business day</summary>
/// <returns>DateTime</returns>
public DateTime FindForwardBusinessDay(DateTime asOf,int daysForward)
{
for (int index = 0; index < daysForward; index++)
{
asOf = FindNextBusinessDay(asOf);
}
return asOf;
}
/// <summary>FindNextBusinessDay - Finds following business day</summary>
/// <returns>DateTime</returns>
public DateTime FindNextBusinessDay(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(1,0,0,0);
asOf=asOf.Add(oneDay);
while(IsWeekend(asOf)||IsHoliday(asOf))asOf=asOf.Add(oneDay);
return asOf;
}
/// <summary>GetPrevBusinessDay - Gets previous business day</summary>
/// <note>If the given date is a business day then this method will return the given date</note>
/// <returns>None</returns>
public DateTime GetPrevBusinessDay(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(1,0,0,0);
while(IsWeekend(asOf)||IsHoliday(asOf))asOf=asOf.Subtract(oneDay);
return asOf;
}
/// <summary>GetNextBusinessDay - Gets next business day</summary>
/// <note>If the given date is a business day then this method will return the given date</note>
/// <returns>None</returns>
public DateTime GetNextBusinessDay(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(1,0,0,0);
while(IsWeekend(asOf)||IsHoliday(asOf))asOf=asOf.Add(oneDay);
return asOf;
}
/// <summary>GetNextDay - Gets next business day</summary>
/// <note>If the given date is a business day then this method will return the given date</note>
/// <returns>None</returns>
public DateTime GetNextDay(DateTime asOf)
{
return asOf.Add(Utility.OneDay);
}
/// <summary>GetPrevFriday - Gets date of prior friday</summary>
/// <note>Get the date of the previous friday - if previous Friday is holiday will seek previous business day</note>
/// <returns>None</returns>
public DateTime GetPrevFriday(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(1,0,0,0);
List<DateTime> historicalDates=null;
int daysToFetch=7;
if(DayOfWeek.Friday==asOf.DayOfWeek)
{
asOf=asOf.Subtract(oneDay);
daysToFetch--;
}
historicalDates=GenerateHistoricalDates(asOf,daysToFetch);
for(int index=0;index<historicalDates.Count;index++)
{
DateTime date=(DateTime)historicalDates[index];
if(DayOfWeek.Friday==date.DayOfWeek)return GetPrevBusinessDay(date);
}
throw new Exception("The week no longer contains Friday?");
}
public DateTime GetCurrentMonthEnd(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(-1,0,0,0);
DateTime date=new DateTime(asOf.Year,asOf.Month,asOf.Day);
date=new DateTime(date.Year,date.Month,DateTime.DaysInMonth(asOf.Year,asOf.Month));
while(IsWeekend(date)||IsHoliday(asOf))date=date.Add(oneDay);
return date;
}
public DateTime GetNextMonthEnd(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(-1,0,0,0);
DateTime date=new DateTime(asOf.Year,asOf.Month,asOf.Day);
date=date.AddMonths(1);
date=new DateTime(date.Year,date.Month,DateTime.DaysInMonth(date.Year,date.Month));
while(IsWeekend(date)||IsHoliday(asOf))date=date.Add(oneDay);
return date;
}
public DateTime GetPrevMonthEnd(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(-1,0,0,0);
DateTime date=new DateTime(asOf.Year,asOf.Month,asOf.Day);
date=date.AddMonths(-1);
date=new DateTime(date.Year,date.Month,DateTime.DaysInMonth(date.Year,date.Month));
while(IsWeekend(date)||IsHoliday(asOf))date=date.Add(oneDay);
return date;
}
public DateTime GetPrevMonthEnd(DateTime asOf,int count)
{
for(int index=0;index<count;index++)
{
asOf=GetPrevMonthEnd(asOf);
}
return asOf;
}
public DateTime EnsureWeekday(DateTime asOf)
{
TimeSpan oneDay=new TimeSpan(1,0,0,0);
if(!IsWeekend(asOf))return asOf;
while(IsWeekend(asOf=asOf.Add(oneDay)));
return asOf;
}
public DateTime GenerateHistoricalDate(DateTime startDate,int dayCount)
{
DateTime histDate;
int datedDates=0;
TimeSpan singleDay;
startDate = startDate.Date;
histDate=startDate;
if(dayCount<0)singleDay=new TimeSpan(-1,0,0,0);
else singleDay=new TimeSpan(1,0,0,0);
dayCount=dayCount<0?-dayCount:dayCount;
while(datedDates<dayCount)
{
if(IsMarketOpen(ref histDate))datedDates++;
histDate=histDate.Subtract(singleDay);
}
return histDate.Add(singleDay);
}
// Does not account for weekends etc.,
public DateTime GenerateFutureDate(DateTime startDate,int dayCount)
{
DateTime futureDate;
int datedDates=0;
TimeSpan singleDay;
startDate = startDate.Date;
futureDate=startDate;
singleDay=new TimeSpan(1,0,0,0);
while(datedDates<dayCount)
{
futureDate=futureDate.Add(singleDay);
datedDates++;
}
return futureDate.Add(singleDay);
}
// Accounts for weekends
public DateTime GenerateFutureBusinessDate(DateTime startDate,int dayCount)
{
DateTime futureDate;
int datedDates=0;
TimeSpan singleDay;
startDate = startDate.Date;
futureDate=startDate;
singleDay=new TimeSpan(1,0,0,0);
while(datedDates<dayCount)
{
if(IsMarketOpen(ref futureDate))datedDates++;
futureDate=futureDate.Add(singleDay);
}
return futureDate.Add(singleDay);
}
public int DaysBetweenActual(DateTime historicalDate)
{
DateTime today = DateTime.Now;
TimeSpan timeSpan = historicalDate.Date - today;
return (int)timeSpan.TotalDays;
}
public int DaysBetweenActual(DateTime historicalDate,DateTime startingDate)
{
TimeSpan timeSpan = historicalDate.Date-startingDate;
int totalDays = (int)timeSpan.TotalDays;
if (historicalDate < startingDate) totalDays = (Math.Abs(totalDays) * -1);
else totalDays = Math.Abs(totalDays);
return totalDays;
}
public DateTime DaysAddActual(DateTime date, int daysActual)
{
TimeSpan days = new TimeSpan(daysActual, 0, 0, 0);
return date + days;
}
public int DaysBetween(DateTime startDate, DateTime endDate)
{
if (startDate > endDate)
{
TimeSpan timeSpan = startDate.Date - endDate.Date;
return (int)timeSpan.TotalDays;
}
else
{
TimeSpan timeSpan = endDate.Date - startDate.Date;
return (int)timeSpan.TotalDays;
}
}
public static List<int> GenerateHistoricalYear(int startYear,int years)
{
List<int> yearsList = new List<int>();
for (int index = 0; index < years; index++)
{
yearsList.Add(startYear);
startYear--;
}
return yearsList;
}
public List<DateTime> GenerateHistoricalDates(DateTime startDate, int dayCount)
{
List<DateTime> histDates=new List<DateTime>();
DateTime histDate;
TimeSpan singleDay;
startDate = startDate.Date;
histDate=startDate;
if(dayCount<0)singleDay=new TimeSpan(-1,0,0,0);
else singleDay=new TimeSpan(1,0,0,0);
dayCount=dayCount<0?-dayCount:dayCount;
while(histDates.Count<dayCount)
{
if(IsMarketOpen(ref histDate))histDates.Add(histDate);
histDate=histDate.Subtract(singleDay);
}
return histDates;
}
// The function will figure out which date is the most recent and which one is the historical date.
// Generally, make startDate the most recent and endDate the historical date.
public List<DateTime> GenerateHistoricalDates(DateTime startDate,DateTime endDate)
{
if (Utility.Epoch.Equals(startDate)||Utility.Epoch.Equals(endDate)) return null;
startDate = startDate.Date;
endDate = endDate.Date;
List<DateTime> histDates = new List<DateTime>();
DateTime histDate;
TimeSpan singleDay;
bool reverse = false;
if (endDate > startDate)
{
reverse = true;
DateTime swap = endDate;
endDate = startDate;
startDate = swap;
}
histDate=startDate;
singleDay=new TimeSpan(1,0,0,0);
while(histDate>=endDate)
{
if(IsMarketOpen(ref histDate))histDates.Add(histDate);
histDate=histDate.Subtract(singleDay);
}
if (reverse) histDates.Reverse();
return histDates;
}
// The function will figure out which date is the most recent and which one is the historical date.
// Generally, make startDate the most recent and endDate the historical date.
public List<DateTime> GenerateHistoricalDatesActual(DateTime startDate, DateTime endDate)
{
if (Utility.Epoch.Equals(startDate) || Utility.Epoch.Equals(endDate)) return null;
startDate = startDate.Date;
endDate = endDate.Date;
List<DateTime> histDates = new List<DateTime>();
DateTime histDate;
TimeSpan singleDay;
bool reverse = false;
if (endDate > startDate)
{
reverse = true;
DateTime swap = endDate;
endDate = startDate;
startDate = swap;
}
histDate = startDate;
singleDay = new TimeSpan(1, 0, 0, 0);
while (histDate >= endDate)
{
histDates.Add(histDate);
histDate = histDate.Subtract(singleDay);
}
if (reverse) histDates.Reverse();
return histDates;
}
private bool IsMarketOpen(ref DateTime dateTime)
{
if(IsWeekend(dateTime)||IsHoliday(dateTime))return false;
return true;
}
public bool IsWeekend(DateTime dateTime)
{
if(DayOfWeek.Sunday==dateTime.DayOfWeek || DayOfWeek.Saturday==dateTime.DayOfWeek)return true;
return false;
}
public bool IsHoliday(DateTime dateTime)
{
if(null==holidays)return false;
return holidays.Contains(dateTime.Date);
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
namespace MarketData.Utils
{
public class DateRange : List<DateTime>
{
public DateRange(DateTime startDate,DateTime endDate)
{
startDate = startDate.Date;
endDate=endDate.Date;
DateGenerator dateGenerator=new DateGenerator();
List<DateTime> dates= dateGenerator.GenerateHistoricalDates(startDate, endDate);
foreach (DateTime date in dates) Add(date);
Sort(); // ensure that no matter how we set this up, the oldest date winds up being at the lowest index of the list
}
public DateTime StartDate
{
get { return this[0]; }
}
public DateTime EndDate
{
get { return this[Count-1]; }
}
}
}

View File

@@ -0,0 +1,159 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Text;
using System.Reflection;
using System.Net;
//using System.Runtime.Remoting.Messaging;
// Filename: MarketDataTrace.cs
// Author:Sean Kessler
// Date:11/2005
namespace MarketData.Utils
{
public enum LogLevel : uint
{
NONE=0x0000,
INFO=0x0002,
DEBUG=0x0004,
VERBOSE=0x0008
};
/// <summary>MarketDataTrace - Utility for .</summary>
public class MDTrace
{
private static LogLevel logLevel=LogLevel.DEBUG;
/// <summary>MarketDataTrace - Private constructor prevents instantiation.</summary>
/// <returns>none</returns>
private MDTrace()
{
}
/// <summary>LogLevel - Get/Set Log level.</summary>
/// <param name="logLevel">The log level.</param>
/// <returns>LogLevel</returns>
public static LogLevel LogLevel
{
get{return logLevel;}
set{logLevel=value;}
}
/// <summary>WriteLine - Writes a line of text to trace log.</summary>
/// <param name="message">string content of message to write.</param>
/// <returns>void</returns>
// [Conditional("TRACE")]
public static void Write(LogLevel logLevel,string message)
{
if(MDTrace.logLevel<logLevel)return;
Trace.Write(GetCallerIP()+GetThreadRep()+GetLogLevelRep()+"["+DateTime.Now.ToString()+"]"+GetMethodInfo()+message);
Console.Write(message);
Flush();
}
/// <summary>WriteLine - Writes a line of text to trace log.</summary>
/// <param name="message">string content of message to write.</param>
/// <returns>void</returns>
// [Conditional("TRACE")]
public static void WriteLine(string message)
{
WriteLine(LogLevel.DEBUG,GetCallerIP()+GetThreadRep()+GetLogLevelRep()+"["+DateTime.Now.ToString()+"]"+" "+GetMethodInfo()+message);
Console.WriteLine(message);
}
/// <summary>WriteLine - Writes a line of text to trace log.</summary>
/// <param name="message">string content of message to write.</param>
/// <returns>void</returns>
// [Conditional("TRACE")]
public static void WriteLine(LogLevel logLevel,Exception exception)
{
if(MDTrace.logLevel<logLevel)return;
Trace.WriteLine(GetCallerIP()+GetThreadRep()+GetLogLevelRep()+"["+DateTime.Now.ToString()+"]"+" "+GetMethodInfo()+exception.ToString());
Console.WriteLine(exception);
Flush();
}
/// <summary>WriteLine - Writes a line of text to trace log.</summary>
/// <param name="message">string content of message to write.</param>
/// <returns>void</returns>
// [Conditional("TRACE")]
public static void WriteLine(LogLevel logLevel,string message)
{
if(MDTrace.logLevel<logLevel)return;
Trace.WriteLine(GetCallerIP()+GetThreadRep()+GetLogLevelRep()+"["+DateTime.Now.ToString()+"]"+" "+GetMethodInfo()+message);
Console.WriteLine(message);
Flush();
}
/// <summary>Indent - set trace log indentation.</summary>
/// <returns>void</returns>
// [Conditional("TRACE")]
public static void Indent()
{
Trace.Indent();
}
/// <summary>Unindent - set trace log indentation back.</summary>
/// <returns>void</returns>
// [Conditional("TRACE")]
public static void Unindent()
{
Trace.Unindent();
}
/// <summary>Flush - Flush trace log buffers to disk.</summary>
/// <returns>void</returns>
// [Conditional("TRACE")]
public static void Flush()
{
Trace.Flush();
}
/// <summary>GetLogLevel - Return current log level.</summary>
/// <returns>LogLevel</returns>
public static LogLevel GetLogLevel(String strLogLevel)
{
if(strLogLevel.Equals("debug"))return LogLevel.DEBUG;
else if(strLogLevel.Equals("verbose"))return LogLevel.VERBOSE;
else if(strLogLevel.Equals("info"))return LogLevel.INFO;
else return LogLevel.NONE;
}
/// <summary>GetLogLevel - Return current log level.</summary>
/// <returns>LogLevel</returns>
private static string GetLogLevelRep()
{
if (MDTrace.logLevel == LogLevel.DEBUG) return "[TRACE.DEBUG]";
else if (MDTrace.logLevel == LogLevel.VERBOSE) return "[TRACE.VERBOSE]";
else if (MDTrace.logLevel == LogLevel.INFO) return "[TRACE.INFO]";
else return "[TRACE.NONE]";
}
/// <summary>GetThreadRep - Return threading information.</summary>
/// <returns>LogLevel</returns>
private static string GetThreadRep()
{
return "[Thread="+Thread.CurrentThread.GetHashCode()+"]";
}
/// <summary>GetMethodInfo - Returns information about the calling method 2 frames up.</summary>
/// <returns>String</returns>
private static String GetMethodInfo()
{
StringBuilder sb=new StringBuilder();
StackFrame frame=new StackFrame(2,true);
MethodBase methodBase=frame.GetMethod();
ParameterInfo[] parameters=methodBase.GetParameters();
sb.Append("[").Append(methodBase.DeclaringType.FullName).Append("::").Append(methodBase.Name).Append("(");
for(int index=0;index<parameters.Length;index++)
{
ParameterInfo parameter=(ParameterInfo)parameters[index];
sb.Append(parameter.Name);
if(!(index==parameters.Length-1))sb.Append(",");
}
sb.Append(")]");
return sb.ToString();
}
/// <summary>GetCallerIP - Returns the calling methods IP address.</summary>
/// <returns>String</returns>
private static String GetCallerIP()
{
String hostName = Dns.GetHostName();
String hostAddress = Dns.GetHostAddresses(hostName).ToString();
if(null!=hostName)hostName=hostName.Split('.')[0];
if(null==hostName && null==hostAddress)return "[LOCAL]";
return "["+hostAddress+"->"+hostName+"]";
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Text;
using System.Collections.Generic;
namespace MarketData.Utils
{
public class NVPDictionary : Dictionary<String,NVP>
{
public NVPDictionary()
{
}
}
public class NVPCollections : List<NVPCollection>
{
public NVPCollections()
{
}
public NVPCollections(List<String> nvpCollections)
{
foreach(String nvpCollectionString in nvpCollections)Add(new NVPCollection(nvpCollectionString));
}
public List<String> ToList()
{
List<String> nvpCollections=new List<String>();
foreach(NVPCollection nvpCollection in this)nvpCollections.Add(nvpCollection.ToString());
return nvpCollections;
}
}
public class NVPCollection : List<NVP>
{
public NVPCollection()
{
}
public NVPCollection(String nvpCollectionString)
{
if(null==nvpCollectionString)return;
String[] nvpItems=nvpCollectionString.Split('|');
if(null==nvpItems)return;
for(int index=0;index<nvpItems.Length;index++)
{
Add(new NVP(nvpItems[index]));
}
}
public NVPDictionary ToDictionary()
{
NVPDictionary dict=new NVPDictionary();
foreach(NVP nvp in this)dict.Add(nvp.Name,nvp);
return dict;
}
public static NVPCollection FromString(String strNVPCollection)
{
return new NVPCollection(strNVPCollection);
}
public override String ToString()
{
StringBuilder sb=new StringBuilder();
for(int index=0;index<Count;index++)
{
NVP nvp=this[index];
sb.Append(nvp.ToString());
if(index<Count-1)sb.Append("|");
}
return sb.ToString();
}
}
public class NVP
{
public NVP(String name,String value)
{
Name=name;
Value=value;
}
public NVP(String nvpString)
{
if(null==nvpString)return;
String[] nvps=nvpString.Split('=');
if(2!=nvps.Length)return;
Name=nvps[0].Trim();
Value=nvps[1].Trim();
}
public T Get<T>()
{
T result=default(T);
try {result = (T)Convert.ChangeType(Value, typeof(T));}
catch {result = default(T);}
return result;
}
public String Name{get;set;}
public String Value{get;set;}
public override String ToString()
{
StringBuilder sb=new StringBuilder();
sb.Append(Name).Append("=").Append(Value);
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Text;
// Filename: Profiler.cs
// Author:Sean Kessler
namespace MarketData.Utils
{
/// <summary>Profiler - Profiler utility class</summary>
public class Profiler
{
[DllImport("kernel32.dll")]
static extern uint GetTickCount();
private uint elapsedTime;
private uint totalTime;
public Profiler()
{
totalTime = GetTickCount();
Start();
}
public void Reset()
{
totalTime = GetTickCount();
Start();
}
public void Start()
{
elapsedTime = GetTickCount();
}
public uint Stop()
{
return elapsedTime = GetTickCount() - elapsedTime;
}
public uint End()
{
return totalTime = GetTickCount() - totalTime;
}
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace MarketData.Utils
{
public class UpdateManager
{
private StreamWriter streamWriter=null;
private FileStream fileStream=null;
private Dictionary<String,String> entries=new Dictionary<String,String>();
public UpdateManager()
{
}
public bool Prepare(String strPathFileName)
{
try
{
String currentWorkingDirectory=Directory.GetCurrentDirectory();
if(!File.Exists(strPathFileName)||IsExpired(strPathFileName))
{
if(File.Exists(strPathFileName))File.Delete(strPathFileName);
fileStream=new FileStream(strPathFileName,FileMode.Create);
streamWriter=new StreamWriter(fileStream);
Console.WriteLine(String.Format("Creating session file:{0}",strPathFileName));
}
else
{
FileStream fileStream=new FileStream(strPathFileName,FileMode.Open);
StreamReader streamReader=new StreamReader(fileStream);
String strLine=null;
while(null!=(strLine=streamReader.ReadLine()))
{
if(!entries.ContainsKey(strLine))entries.Add(strLine,strLine);
}
Console.WriteLine(String.Format("Loaded {0} entries from session file:{1}",entries.Count,strPathFileName));
streamReader.Close();
streamReader.Dispose();
fileStream.Close();
fileStream.Dispose();
fileStream=new FileStream(strPathFileName,FileMode.Append);
streamWriter=new StreamWriter(fileStream);
}
return true;
}
catch(Exception exception)
{
Console.WriteLine(String.Format("Exception:{0}",exception));
return false;
}
}
private bool IsExpired(String strPathFileName)
{
try
{
DateGenerator dateGenerator=new DateGenerator();
DateTime creationTime=File.GetCreationTime(strPathFileName);
int daysElapsed=Math.Abs(dateGenerator.DaysBetweenActual(creationTime,DateTime.Now));
if(daysElapsed>5)
{
Console.WriteLine(String.Format("{0} is expired. {1} days old.",strPathFileName,daysElapsed));
return true;
}
return false;
}
catch(Exception exception)
{
Console.WriteLine(String.Format("Exception:{0}",exception));
return true;
}
}
public List<String> Entries
{
get{return new List<String>(entries.Keys);}
}
public void Add(String entry)
{
if(null==streamWriter)return;
streamWriter.WriteLine(entry);
streamWriter.Flush();
}
public void Dispose()
{
if(null!=streamWriter){streamWriter.Close();streamWriter.Dispose();}
if(null!=fileStream){fileStream.Close();fileStream.Dispose();}
}
}
}

View File

@@ -0,0 +1,561 @@
using System;
using System.Text;
using System.IO.Compression;
using System.IO;
using System.Globalization;
using System.Linq;
using Microsoft.Win32;
using System.Diagnostics;
using System.Collections.Generic;
using MarketData.MarketDataModel;
namespace MarketData.Utils
{
public class Utility
{
private static DateTime epoch = DateTime.Parse("01-01-0001");
private static TimeSpan oneDay=new TimeSpan(1,0,0,0);
public static String Pad(string str, char filler, int length)
{
int stringLength = str.Length;
if (stringLength >= length) return str;
StringBuilder sb = new StringBuilder();
while (stringLength < length)
{
sb.Append(filler);
stringLength++;
}
return sb.ToString() + str;
}
public static String RemoveHtml(String strItem)
{
String[] codes = { "&#x27;","&#187;" };
if(null==strItem)return strItem;
foreach (String code in codes)
{
strItem = strItem.Replace(code,"'");
}
return strItem;
// String str=strItem.Replace("&#x27;","'");
// return str;
}
public static String RemoveDivs(String strItem)
{
StringBuilder sb=new StringBuilder();
bool inDiv=false;
if(null==strItem)return strItem;
for(int index=0;index<strItem.Length;index++)
{
char ch=strItem[index];
if(ch.Equals('<'))inDiv=true;
else if(ch.Equals('>'))inDiv=false;
else if(!inDiv)sb.Append(ch);
}
return sb.ToString();
}
public static String BetweenString(String strItem, String strBegin, String strEnd)
{
if (null == strItem) return null;
int index=-1;
if(null==strBegin)index=0;
else index = strItem.IndexOf(strBegin);
if (-1 == index) return null;
String str = null;
if(null!=strBegin)str=strItem.Substring(index + strBegin.Length);
else str=strItem;
if(null==strEnd)return str;
index = str.IndexOf(strEnd);
if (-1 == index) return null;
StringBuilder sb = new StringBuilder();
for (int strIndex = 0; strIndex < str.Length; strIndex++)
{
if (index == strIndex) break;
sb.Append(str[strIndex]);
}
return sb.ToString();
}
public static String RemoveAfter(String strItem, char charItem)
{
StringBuilder sb = new StringBuilder();
for (int index = 0; index < strItem.Length; index++)
{
char ch = strItem[index];
if (ch.Equals(charItem)) break;
sb.Append(ch);
}
return sb.ToString();
}
public static bool OutOfRange(double value)
{
return value > 100000000000000000000.00 || value< -99999999999999999999.99;
}
public static String RemoveControlChars(String strItem)
{
StringBuilder sb=new StringBuilder();
for(int index=0;index<strItem.Length;index++)
{
char ch=strItem[index];
if(!char.IsControl(ch))sb.Append(ch);
}
return sb.ToString();
}
public static String GetPath(String strPathFileName)
{
int index=strPathFileName.LastIndexOf('\\');
if (-1 == index) return null;
String strPath = strPathFileName.Substring(0, index);
return strPath;
}
public static String KeepBefore(String strItem,String strKeepBefore)
{
int startPos=strItem.IndexOf(strKeepBefore);
if(-1==startPos)return null;
return strItem.Substring(0,startPos);
}
public static String KeepAfter(String strItem,String strKeepAfter)
{
int startPos=strItem.IndexOf(strKeepAfter);
if(-1==startPos)return null;
return strItem.Substring(startPos+strKeepAfter.Length);
}
public static String KeepAfterLast(String strItem,String strKeepAfter)
{
if(null==strItem)return null;
int startPos=strItem.LastIndexOf(strKeepAfter);
if(-1==startPos)return null;
return strItem.Substring(startPos+strKeepAfter.Length);
}
public static String Find(String strItem,String search,char delimeter)
{
if(null==strItem)return null;
bool foundDelimeter=false;
StringBuilder sb=new StringBuilder();
int startPos=strItem.LastIndexOf(search);
if(-1==startPos)return null;
startPos+=search.Length;
for(;startPos<strItem.Length;startPos++)
{
char ch=strItem[startPos];
if(ch.Equals(delimeter))
{
foundDelimeter=true;
break;
}
sb.Append(ch);
}
if(!foundDelimeter)return null;
return sb.ToString();
}
public static String FindFirst(String strItem,String search,char delimeter)
{
if(null==strItem)return null;
bool foundDelimeter=false;
StringBuilder sb=new StringBuilder();
int startPos=strItem.IndexOf(search);
if(-1==startPos)return null;
startPos+=search.Length;
for(;startPos<strItem.Length;startPos++)
{
char ch=strItem[startPos];
if(ch.Equals(delimeter))
{
foundDelimeter=true;
break;
}
sb.Append(ch);
}
if(!foundDelimeter)return null;
return sb.ToString();
}
public static String AddQuotes(String item)
{
return "\"" + item + "\"";
}
public static long DateToLong(DateTime date)
{
int year = date.Year;
int month = date.Month;
int day = date.Day;
return (year * 10000) + (month * 100) + day;
}
public static DateTime LongToDate(long longDate)
{
int year = (int)(longDate / 10000);
int month = ((int)longDate / 100) - year * 100;
int day = (int)(longDate - ((int)(longDate / 100)) * 100);
return new DateTime(year, month, day);
}
public static String DateTimeToStringHHMMSS(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("HH:mm:ss");
}
public static String DateTimeToStringMMSDDSYYYY(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("MM/dd/yyyy");
}
public static String DateTimeToStringMMSYYYY(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("MM/yyyy");
}
public static String DateTimeToStringMMSYY(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("MM/yy");
}
public static String DateTimeToStringMMSDDSYYYYHHMMSS(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("MM/dd/yyyy hh:mm:ss");
}
public static String DateTimeToStringMMHDDHYYYY(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("MM-dd-yyyy");
}
public static String DateTimeToStringYYYYHMMHDD(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("yyyy-MM-dd");
}
public static String DateTimeToStringYYYYHMMHDDHHMMSS(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("yyyy-MM-dd HH:MM:ss");
}
public static String DateTimeToStringYYYYMMDD(DateTime dateTime)
{
if (Utility.IsEpoch(dateTime)) return "";
return dateTime.ToString("yyyyMMdd");
}
public static String AsteriskForString(String str)
{
StringBuilder sb = new StringBuilder();
int length = str.Length;
for (int index = 0; index < length; index++) sb.Append("*");
return sb.ToString();
}
public static String FormatNumber(double number)
{
StringBuilder sb=new StringBuilder();
if (double.NaN.Equals(number))sb.Append("N/A");
else sb.Append(String.Format("{0:0.000}", number));
return sb.ToString();
}
public static String FormatNumberConstrain(double value,int places=1,bool commas=false)
{
String strValue=null;
if(value>=1000)
{
value/=1000;
strValue=Utility.FormatNumber(value,places,commas)+"K";
}
else if(value>=1000000)
{
value/=1000000;
strValue=Utility.FormatNumber(value,places,commas)+"M";
}
else if(value>=1000000000)
{
value/=1000000000;
strValue=Utility.FormatNumber(value,places,commas)+"B";
}
else
{
strValue=Utility.FormatNumber(value,places,commas);
}
return strValue;
}
public static String FormatNumber(double number,int places,bool commas=false)
{
StringBuilder sb = new StringBuilder();
StringBuilder formatString=new StringBuilder();
if (commas&&number>=1000.00) formatString.Append("{0:0,0.");
else formatString.Append("{0:0.");
for(int index=0;index<places;index++)formatString.Append("0");
formatString.Append("}");
if (double.NaN.Equals(number)) sb.Append("N/A");
else sb.Append(String.Format(formatString.ToString(), number));
return sb.ToString();
}
public static String FormatCurrency(double number)
{
StringBuilder sb=new StringBuilder();
if (double.NaN.Equals(number))sb.Append("N/A");
else sb.Append(String.Format("{0:C}", number));
return sb.ToString();
}
public static String FormatCurrency(double number,int decimals)
{
StringBuilder sb=new StringBuilder();
String currencyFormat="{0:C"+decimals+"}";
if (double.NaN.Equals(number))sb.Append("N/A");
else sb.Append(String.Format(currencyFormat, number));
return sb.ToString();
}
public static String FormatPercent(double number)
{
StringBuilder sb = new StringBuilder();
if (double.NaN.Equals(number)) sb.Append("N/A");
else sb.Append(String.Format("{0:P}", number));
return sb.ToString();
}
public static String ConformDate(String strDate)
{
String[] elements=strDate.Split(' ');
if(elements.Length<3)return strDate;
return elements[0]+" "+elements[1]+" "+elements[2];
}
public static DateTime ParseDate(String strDate)
{
System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-US");
String[] formats = new[] {"dddd, MMMM dd","MMM dd yyyy","yyyy-MM","ddd, MMM. d","ddd, MMM. dd", "yyyy/MM/dd","M-d-yyyy", "dd-MM-yyyy", "MM-dd-yyyy", "M.d.yyyy", "dd.MM.yyyy", "MM.dd.yyyy","yyyyMMdd" }.Union(cultureInfo.DateTimeFormat.GetAllDateTimePatterns()).ToArray();
strDate = strDate.Trim();
DateTime dateTime=DateTime.ParseExact(strDate, formats, new System.Globalization.CultureInfo("en-US"), DateTimeStyles.AssumeLocal);
return dateTime;
}
public static double ParsePercent(String strPercent)
{
if (null == strPercent) return double.NaN;
strPercent = strPercent.Replace("%", null);
try { return double.Parse(strPercent)/100.00; }
catch (Exception) { return double.NaN; }
}
public static double ParseCurrency(String strNumber)
{
if (null == strNumber) return double.NaN;
if(Constants.CONST_DASHES.Equals(strNumber))return double.NaN;
strNumber = strNumber.Replace("$", null);
strNumber = strNumber.Replace(",", null);
strNumber = strNumber.Replace("(", "-");
strNumber = strNumber.Replace(")", null);
if (strNumber.Equals("")) return double.NaN;
try { return double.Parse(strNumber); }
catch (Exception) { return double.NaN; }
}
public static String FormatCurrencyWithQuotes(double number)
{
return AddQuotes(FormatCurrency(number));
}
public static String FormatDates(DateTime d1, DateTime d2)
{
StringBuilder sb=new StringBuilder();
sb.Append(Utility.DateTimeToStringMMSDDSYYYY(d1)).Append("-");
sb.Append(Utility.DateTimeToStringMMSDDSYYYY(d2));
return sb.ToString();
}
public static String TrimToSpace(String strString)
{
if (null == strString) return strString;
StringBuilder sb = new StringBuilder();
for (int index = 0; index < strString.Length; index++)
{
char ch=strString[index];
if (' '.Equals(ch)) break;
sb.Append(ch);
}
return sb.ToString();
}
public static String BooleanToYesNoString(bool booleanValue)
{
return booleanValue ? "Yes" : "No";
}
public static bool IsEpoch(DateTime dateTime)
{
return dateTime.Equals(epoch);
}
public static DateTime Epoch
{
get { return epoch; }
}
public static TimeSpan OneDay
{
get{return oneDay;}
}
public static String ListToString(List<String> list,char separator=',')
{
StringBuilder sb=new StringBuilder();
if (null == list || 0 == list.Count) return null;
for(int index=0;index<list.Count;index++)
{
sb.Append(list[index]);
if(index<list.Count-1)sb.Append(separator);
}
return sb.ToString();
}
public static List<String> ToList(String items,char separator=',')
{
List<String> list = items.Split(separator).ToList<String>();
list=(from String s in list select s.Trim()).ToList<String>();
return list;
}
public static String FromList(List<String> items,String postFix=",")
{
StringBuilder sb=new StringBuilder();
for(int index=0;index<items.Count;index++)
{
sb.Append(items[index]);
if(index<items.Count-1)sb.Append(postFix);
}
return sb.ToString();
}
public static byte[] Compress(String strString)
{
MemoryStream outputStream = null;
GZipStream compressionStream = null;
try
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strString);
outputStream = new MemoryStream();
compressionStream = new GZipStream(outputStream, CompressionMode.Compress, true);
compressionStream.Write(bytes, 0, bytes.Length);
compressionStream.Close();
compressionStream = null;
byte[] outputBytes = outputStream.ToArray();
outputStream.Close();
outputStream = null;
return outputBytes;
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,exception);
return null;
}
finally
{
if (null != compressionStream)
{
compressionStream.Close();
compressionStream = null;
}
if (null != outputStream)
{
outputStream.Close();
outputStream = null;
}
}
}
public static String Decompress(byte[] compressedBytes)
{
MemoryStream compressedStream = new MemoryStream(compressedBytes);
GZipStream decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress,true);
MemoryStream outputStream=new MemoryStream();
try
{
byte[] decompressedBytesBuffer = new byte[4096];
int count = 0;
while (true)
{
count = decompressionStream.Read(decompressedBytesBuffer, 0, decompressedBytesBuffer.Length);
if (count > 0) outputStream.Write(decompressedBytesBuffer, 0, count);
else break;
}
decompressionStream.Close();
compressedStream.Close();
String strDecompressed = System.Text.Encoding.UTF8.GetString(outputStream.ToArray());
outputStream.Close();
outputStream = null;
compressedStream = null;
decompressionStream = null;
return strDecompressed;
}
catch (Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,exception);
return null;
}
finally
{
if (null != outputStream)
{
outputStream.Close();
outputStream = null;
}
if (null != decompressionStream)
{
decompressionStream.Close();
decompressionStream = null;
}
if (null != compressedStream)
{
compressedStream.Close();
compressedStream = null;
}
}
}
public static void LaunchBrowserSearch(String searchTerm)
{
Process.Start("https://www.google.com/search?q="+Uri.EscapeDataString(searchTerm)+"/");
// OpenWebCommand = new Command(async () => await Browser.OpenAsync("https://www.google.com"));
}
public static bool IsZeroOrNaN(double value)
{
return IsNaN(value)||IsZero(value);
}
private static bool IsZero(double value)
{
if(value==0.00)return true;
return false;
}
private static bool IsNaN(double value)
{
return double.IsNaN(value);
}
public static void DeleteFile(String pathFileName)
{
if(!File.Exists(pathFileName))return;
try{File.Delete(pathFileName);}catch(Exception){;}
}
private static DateTime GetRunDate(String strPathFileName)
{
DateTime runDate=DateTime.Now.Date;
DateGenerator dateGenerator=new DateGenerator();
StreamWriter streamWriter=null;
StreamReader streamReader=null;
try
{
if(!File.Exists(strPathFileName))
{
streamWriter=File.CreateText(strPathFileName);
streamWriter.WriteLine(Utility.DateTimeToStringMMHDDHYYYY(runDate));
streamWriter.Flush();
streamWriter.Close();
streamWriter=null;
return runDate;
}
streamReader=File.OpenText(strPathFileName);
String strLine=streamReader.ReadLine();
streamReader.Close();
streamReader=null;
runDate=Utility.ParseDate(strLine);
if(dateGenerator.DaysBetweenActual(runDate,DateTime.Now)>5)
{
File.Delete(strPathFileName);
runDate=DateTime.Now.Date;
streamWriter=File.CreateText(strPathFileName);
streamWriter.WriteLine(Utility.DateTimeToStringMMHDDHYYYY(runDate));
streamWriter.Flush();
streamWriter.Close();
streamWriter=null;
return runDate;
}
return runDate;
}
catch(Exception exception)
{
MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetRunDate:{0}",exception.ToString()));
return runDate;
}
finally
{
if(null!=streamWriter)streamWriter.Close();
if(null!=streamReader)streamReader.Close();
}
}
}
}

Binary file not shown.

View File

@@ -0,0 +1,19 @@
Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories) and given a Build Action of "AndroidAsset".
These files will be deployed with your package and will be accessible using Android's
AssetManager, like this:
public class ReadAsset : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
InputStream input = Assets.Open ("my_asset.txt");
}
}
Additionally, some Android functions will automatically load asset files:
Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");

View File

@@ -0,0 +1,63 @@
using Android.Content;
using Android.Widget;
using Navigator.Core;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Navigator.Droid;
using Android.Views.InputMethods;
[assembly: ExportRenderer(typeof(EntryWithCustomKeyboardReturnButton), typeof(EntryWithCustomKeyboardReturnButtonCustomRenderer))]
namespace Navigator.Droid
{
public class EntryWithCustomKeyboardReturnButtonCustomRenderer : EntryRenderer
{
public EntryWithCustomKeyboardReturnButtonCustomRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
var customEntry = Element as EntryWithCustomKeyboardReturnButton;
if (Control != null && customEntry != null)
{
SetKeyboardButtonType(customEntry.ReturnType);
Control.EditorAction += (object sender, TextView.EditorActionEventArgs args) =>
{
if (customEntry?.ReturnType != ReturnType.Next)customEntry?.Unfocus();
customEntry?.InvokeCompleted();
};
}
}
void SetKeyboardButtonType(ReturnType returnType)
{
switch (returnType)
{
case ReturnType.Go:
Control.ImeOptions = ImeAction.Go;
Control.SetImeActionLabel("Go", ImeAction.Go);
break;
case ReturnType.Next:
Control.ImeOptions = ImeAction.Next;
Control.SetImeActionLabel("Next", ImeAction.Next);
break;
case ReturnType.Send:
Control.ImeOptions = ImeAction.Send;
Control.SetImeActionLabel("Send", ImeAction.Send);
break;
case ReturnType.Search:
Control.ImeOptions = ImeAction.Search;
Control.SetImeActionLabel("Search", ImeAction.Search);
break;
default:
Control.ImeOptions = ImeAction.Done;
Control.SetImeActionLabel("Done", ImeAction.Done);
break;
}
}
}
}

View File

@@ -0,0 +1,30 @@

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
namespace Navigator.Droid
{
[Activity(Label = "Navigator", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{60911697-7A92-4A97-B1DF-6DC9692AAAFB}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TemplateGuid>{9AA2D3C6-3393-45F1-8E7C-5A9901728795}</TemplateGuid>
<OutputType>Library</OutputType>
<RootNamespace>Navigator.Droid</RootNamespace>
<AssemblyName>Navigator.Android</AssemblyName>
<Deterministic>True</Deterministic>
<AndroidApplication>True</AndroidApplication>
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
<AndroidUseAapt2>true</AndroidUseAapt2>
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidLinkMode>None</AndroidLinkMode>
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
<BundleAssemblies>false</BundleAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidManagedSymbols>true</AndroidManagedSymbols>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.3</Version>
</PackageReference>
<PackageReference Include="SkiaSharp.Views.Forms">
<Version>1.68.3</Version>
</PackageReference>
<PackageReference Include="Xamarin.Forms" Version="4.5.0.495" />
<PackageReference Include="Xamarin.Essentials" Version="1.5.3.2" />
</ItemGroup>
<ItemGroup>
<Compile Include="CustomEntryRenderer.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\AboutResources.txt" />
<None Include="Assets\AboutAssets.txt" />
<None Include="Properties\AndroidManifest.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\Tabbar.xml" />
<AndroidResource Include="Resources\layout\Toolbar.xml" />
<AndroidResource Include="Resources\values\styles.xml" />
<AndroidResource Include="Resources\values\colors.xml" />
<AndroidResource Include="Resources\mipmap-anydpi-v26\icon.xml" />
<AndroidResource Include="Resources\mipmap-anydpi-v26\icon_round.xml" />
<AndroidResource Include="Resources\mipmap-hdpi\icon.png" />
<AndroidResource Include="Resources\mipmap-hdpi\launcher_foreground.png" />
<AndroidResource Include="Resources\mipmap-mdpi\icon.png" />
<AndroidResource Include="Resources\mipmap-mdpi\launcher_foreground.png" />
<AndroidResource Include="Resources\mipmap-xhdpi\icon.png" />
<AndroidResource Include="Resources\mipmap-xhdpi\launcher_foreground.png" />
<AndroidResource Include="Resources\mipmap-xxhdpi\icon.png" />
<AndroidResource Include="Resources\mipmap-xxhdpi\launcher_foreground.png" />
<AndroidResource Include="Resources\mipmap-xxxhdpi\icon.png" />
<AndroidResource Include="Resources\mipmap-xxxhdpi\launcher_foreground.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Navigator\Navigator.csproj">
<Project>{D7B02C08-551B-4635-9AA5-8DB647762DAC}</Project>
<Name>Navigator</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Assemblies\" />
<Folder Include="Resources\xml\" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\launcher_foreground.png">
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\stop.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-hdpi\stop.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-mdpi\stop.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xhdpi\stop.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxhdpi\stop.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxxhdpi\stop.png" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.navigator">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
<application android:label="Navigator.Android"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:usesCleartextTraffic="true">
android:networkSecurityConfig="@xml/network_security_config"&gt;
</application>
</manifest>

View File

@@ -0,0 +1,30 @@
using System.Reflection;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Navigator.Android")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Navigator.Android")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Application(UsesCleartextTraffic = true)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]

View File

@@ -0,0 +1,50 @@
Images, layout descriptions, binary blobs and string dictionaries can be included
in your application as resource files. Various Android APIs are designed to
operate on the resource IDs instead of dealing with images, strings or binary blobs
directly.
For example, a sample Android app that contains a user interface layout (main.xml),
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
would keep its resources in the "Resources" directory of the application:
Resources/
drawable-hdpi/
icon.png
drawable-ldpi/
icon.png
drawable-mdpi/
icon.png
layout/
main.xml
values/
strings.xml
In order to get the build system to recognize Android resources, set the build action to
"AndroidResource". The native Android APIs do not operate directly with filenames, but
instead operate on resource IDs. When you compile an Android application that uses resources,
the build system will package the resources for distribution and generate a class called
"Resource" that contains the tokens for each one of the resources included. For example,
for the above Resources layout, this is what the Resource class would expose:
public class Resource {
public class drawable {
public const int icon = 0x123;
}
public class layout {
public const int main = 0x456;
}
public class strings {
public const int first_string = 0xabc;
public const int second_string = 0xbcd;
}
}
You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main
to reference the layout/main.xml file, or Resource.strings.first_string to reference the first
string in the dictionary file values/strings.xml.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.TabLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabIndicatorColor="@android:color/white"
app:tabGravity="fill"
app:tabMode="fixed" />

View File

@@ -0,0 +1,9 @@
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/launcher_background" />
<foreground android:drawable="@mipmap/launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/launcher_background" />
<foreground android:drawable="@mipmap/launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="launcher_background">#FFFFFF</color>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MainTheme" parent="MainTheme.Base">
</style>
<!-- Base theme applied no matter what API -->
<style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
<item name="windowNoTitle">true</item>
<!--We will be using the toolbar so no need to show ActionBar-->
<item name="windowActionBar">false</item>
<!-- Set theme colors from https://aka.ms/material-colors -->
<!-- colorPrimary is used for the default action bar background -->
<item name="colorPrimary">#2196F3</item>
<!-- colorPrimaryDark is used for the status bar -->
<item name="colorPrimaryDark">#1976D2</item>
<!-- colorAccent is used as the default value for colorControlActivated
which is used to tint widgets -->
<item name="colorAccent">#FF4081</item>
<!-- You can also set colorControlNormal, colorControlActivated
colorControlHighlight and colorSwitchThumbNormal. -->
<item name="windowActionModeOverlay">true</item>
<item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
</style>
<style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#FF4081</item>
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">192.168.0.73</domain>
<domain includeSubdomains="true">73.245.214.234</domain>
</domain-config>
</network-security-config>

View File

@@ -0,0 +1 @@
6B8CA115B17E1795

Binary file not shown.

View File

@@ -0,0 +1 @@
4E033C3C3FAF266A

Some files were not shown because too many files have changed in this diff Show More