Init
330
.gitignore
vendored
Normal 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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
32
DataDisplay/Common/DrawingHelper.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
162
DataDisplay/Common/GridLines.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
DataDisplay/Common/PointMapping.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
58
DataDisplay/Controls/RenderView.cs
Normal 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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
19
DataDisplay/DataDisplay.csproj
Normal 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>
|
||||
25
DataDisplay/DataDisplay.sln
Normal 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
|
||||
129
DataDisplay/DataSource/CompositeDataSource.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
14
DataDisplay/DataSource/DataSourceExtensions.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
110
DataDisplay/DataSource/EnumerableDataSource.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
DataDisplay/DataSource/EnumerableDataSourceBase.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
37
DataDisplay/DataSource/EnumerablePointEnumerator.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
DataDisplay/DataSource/IPointDataSource.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
22
DataDisplay/DataSource/IPointEnumerator.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
16
DataDisplay/DataSource/Mapping.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
77
DataDisplay/Graph/LineGraph.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
DataDisplay/Renderers/CircleRenderer.cs
Normal 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;
|
||||
// }
|
||||
//}
|
||||
11
DataDisplay/Renderers/IRenderer.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace DataDisplay.Renderers
|
||||
{
|
||||
public interface IRenderer
|
||||
{
|
||||
void PaintSurface(SKSurface surface, SKImageInfo info);
|
||||
event EventHandler RefreshRequested;
|
||||
}
|
||||
}
|
||||
13
MarketDataLib/MarketDataLib.csproj
Normal 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>
|
||||
161
MarketDataLib/MarketDataModel/BollingerBand.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
MarketDataLib/MarketDataModel/Constants.cs
Normal 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.";
|
||||
}
|
||||
}
|
||||
37
MarketDataLib/MarketDataModel/GainLoss.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
35
MarketDataLib/MarketDataModel/GainLoss/DMAValue.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
21
MarketDataLib/MarketDataModel/GainLoss/DMAValues.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
MarketDataLib/MarketDataModel/GainLoss/GainLossItem.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
49
MarketDataLib/MarketDataModel/GainLoss/TotalGainLossItem.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
MarketDataLib/MarketDataModel/Headlines.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
|
||||
51
MarketDataLib/MarketDataModel/MobileDataModels.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
96
MarketDataLib/MarketDataModel/ModelTrade.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
23
MarketDataLib/MarketDataModel/ParityElement.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
107
MarketDataLib/MarketDataModel/Portfolio.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
MarketDataLib/MarketDataModel/PortfolioTrade.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
179
MarketDataLib/MarketDataModel/PortfolioTrades.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
MarketDataLib/MarketDataModel/PositionWithDescription.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
19
MarketDataLib/MarketDataModel/PremarketElement.cs
Normal 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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
28
MarketDataLib/MarketDataModel/PriceIndex.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
448
MarketDataLib/MarketDataModel/Prices.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
14
MarketDataLib/MarketDataModel/StopLimit.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
144
MarketDataLib/MarketDataModel/TimeSeriesElement.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
139
MarketDataLib/Numerics/BetaGenerator.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
66
MarketDataLib/Numerics/Bin.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
73
MarketDataLib/Numerics/BlackScholes.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
52
MarketDataLib/Numerics/KStest.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
}
|
||||
134
MarketDataLib/Numerics/LeastSquares.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1497
MarketDataLib/Numerics/Numerics.cs
Normal file
114
MarketDataLib/Numerics/Spline.cs
Normal 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
|
||||
18
MarketDataLib/Service/Authorization.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
617
MarketDataLib/Service/MarketDataServiceClient.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
32
MarketDataLib/Service/ServiceResult.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
57
MarketDataLib/Utility/CSVLineHelper.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
344
MarketDataLib/Utility/DateGenerator.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
MarketDataLib/Utility/DateRange.cs
Normal 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]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
159
MarketDataLib/Utility/MDTrace.cs
Normal 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+"]";
|
||||
}
|
||||
}
|
||||
}
|
||||
99
MarketDataLib/Utility/NVP.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
43
MarketDataLib/Utility/Profiler.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
93
MarketDataLib/Utility/UpdateManager.cs
Normal 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();}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
561
MarketDataLib/Utility/Utility.cs
Normal 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 = { "'","»" };
|
||||
if(null==strItem)return strItem;
|
||||
foreach (String code in codes)
|
||||
{
|
||||
strItem = strItem.Replace(code,"'");
|
||||
}
|
||||
return strItem;
|
||||
// String str=strItem.Replace("'","'");
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Navigator.Android/Assemblies/MySql.Data.dll
Normal file
19
Navigator.Android/Assets/AboutAssets.txt
Normal 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");
|
||||
63
Navigator.Android/CustomEntryRenderer.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Navigator.Android/MainActivity.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
134
Navigator.Android/Navigator.Android.csproj
Normal 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>
|
||||
10
Navigator.Android/Properties/AndroidManifest.xml
Normal 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">
|
||||
</application>
|
||||
</manifest>
|
||||
30
Navigator.Android/Properties/AssemblyInfo.cs
Normal 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)]
|
||||
50
Navigator.Android/Resources/AboutResources.txt
Normal 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.
|
||||
17163
Navigator.Android/Resources/Resource.designer.cs
generated
Normal file
BIN
Navigator.Android/Resources/drawable/launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
Navigator.Android/Resources/drawable/stop.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
11
Navigator.Android/Resources/layout/Tabbar.xml
Normal 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" />
|
||||
9
Navigator.Android/Resources/layout/Toolbar.xml
Normal 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" />
|
||||
|
||||
5
Navigator.Android/Resources/mipmap-anydpi-v26/icon.xml
Normal 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>
|
||||
@@ -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>
|
||||
BIN
Navigator.Android/Resources/mipmap-hdpi/icon.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Navigator.Android/Resources/mipmap-hdpi/launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
Navigator.Android/Resources/mipmap-hdpi/stop.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Navigator.Android/Resources/mipmap-mdpi/icon.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
Navigator.Android/Resources/mipmap-mdpi/launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Navigator.Android/Resources/mipmap-mdpi/stop.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Navigator.Android/Resources/mipmap-xhdpi/icon.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
Navigator.Android/Resources/mipmap-xhdpi/launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
Navigator.Android/Resources/mipmap-xhdpi/stop.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Navigator.Android/Resources/mipmap-xxhdpi/icon.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 69 KiB |
BIN
Navigator.Android/Resources/mipmap-xxhdpi/stop.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Navigator.Android/Resources/mipmap-xxxhdpi/icon.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 114 KiB |
BIN
Navigator.Android/Resources/mipmap-xxxhdpi/stop.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
7
Navigator.Android/Resources/values/colors.xml
Normal 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>
|
||||
30
Navigator.Android/Resources/values/styles.xml
Normal 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>
|
||||
@@ -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>
|
||||
1
Navigator.Android/lp/0.stamp
Normal file
@@ -0,0 +1 @@
|
||||
6B8CA115B17E1795
|
||||
BIN
Navigator.Android/lp/0/jl/formsviewgroup.jar
Normal file
1
Navigator.Android/lp/41.stamp
Normal file
@@ -0,0 +1 @@
|
||||
4E033C3C3FAF266A
|
||||