Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ce95911
Added draft of API (see README.md inside)
romech Nov 18, 2017
1e7c5fc
Fixed issue with submodule
romech Nov 20, 2017
894f4cc
Edited readme
romech Nov 20, 2017
1334242
Replaced a model with "Candle"
romech Nov 20, 2017
b14ee6c
Replaced a model with "Candle"
romech Nov 20, 2017
765b06b
Splited model into two
romech Nov 27, 2017
6fb8a59
Changed connection settings. Added DB Initializer
romech Nov 28, 2017
9d2516e
Made a couple of controllers to return data from DB
romech Nov 28, 2017
298936f
Added pattern repository
whitec10ud Dec 4, 2017
817572d
Merge remote-tracking branch 'origin/api_draft' into api_draft
whitec10ud Dec 4, 2017
157c14c
Added instructions for Windows
romech Dec 4, 2017
adadc7b
Repository pattern moved to another project
whitec10ud Dec 4, 2017
93d6a50
Merge remote-tracking branch 'origin/api_draft' into api_draft
whitec10ud Dec 4, 2017
bf077db
Manually merged Downloader into API
romech Dec 5, 2017
4a6d676
Merge with earlier commit by NataliaPonomarevaMM
romech Dec 5, 2017
ecd0ad0
Fixed error: couldn't run w/o Main() in Repository
romech Dec 5, 2017
d521be3
Added entity "Instrument"
romech Dec 5, 2017
92e7b40
Even more entities added :)
romech Dec 5, 2017
7f3c2a2
Added pretty ER diagram
romech Dec 5, 2017
901a4fe
Revised enitites
romech Dec 10, 2017
7831922
Added web interface for download tasks
romech Dec 10, 2017
6c4052d
Added api/v0/quotes/filter?instrument=...
romech Dec 11, 2017
2be10f1
Made /quotes/filter work
romech Dec 11, 2017
618aa42
Solved a problem of intersecting data sets
romech Dec 12, 2017
85bfc8b
Minor improvements
romech Dec 12, 2017
0c47117
Added batch deletion
romech Dec 12, 2017
56e8dac
Minor change to /api/v0/quotes
romech Dec 14, 2017
9df5b10
Fixed a little bug
romech Dec 14, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
CoreDownloader/CoreDownloader/bin
CoreDownloader/CoreDownloader/obj

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
1 change: 1 addition & 0 deletions CoreDownloader/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
22 changes: 22 additions & 0 deletions CoreDownloader/CoreDownloader.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.0.0
MinimumVisualStudioVersion = 10.0.0.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreDownloader", "CoreDownloader/CoreDownloader.csproj", "{A31E572A-0AEC-4DBB-95CC-73D444191FBA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A31E572A-0AEC-4DBB-95CC-73D444191FBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A31E572A-0AEC-4DBB-95CC-73D444191FBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A31E572A-0AEC-4DBB-95CC-73D444191FBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A31E572A-0AEC-4DBB-95CC-73D444191FBA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
10 changes: 10 additions & 0 deletions CoreDownloader/CoreDownloader/CoreDownloader.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Without Repo|AnyCPU'" />
<ItemGroup>
<PackageReference Include="FluentScheduler" Version="5.3.0" />
</ItemGroup>
</Project>
22 changes: 22 additions & 0 deletions CoreDownloader/CoreDownloader/CoreDownloader.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.0.0
MinimumVisualStudioVersion = 10.0.0.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreDownloader", "CoreDownloader.csproj", "{BFAA137B-F2DB-4D32-94D9-34AE559DCA23}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BFAA137B-F2DB-4D32-94D9-34AE559DCA23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFAA137B-F2DB-4D32-94D9-34AE559DCA23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFAA137B-F2DB-4D32-94D9-34AE559DCA23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFAA137B-F2DB-4D32-94D9-34AE559DCA23}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
67 changes: 67 additions & 0 deletions CoreDownloader/CoreDownloader/Data.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;

namespace CoreDownloader
{
/// <summary>
/// Class for saving data; waiting for database response to adjust the fromat
/// there are all types of data that i have met, may be there are others type - need to figure out it
/// </summary>
public class Data
{
public static int NumberOfFields { get; } = 9;

public string _ticker; // HEY
public string _per; // Sorry for making them public,
public string _date; // but I don't know how to access them
public string _time;
public string _open;
public string _high;
public string _low;
public string _close;
public string _vol;

public Data()
{
_ticker = null;
_per = null;
_date = null;
_time = null;
_open = null;
_high = null;
_low = null;
_close = null;
_vol = null;

}

/// <summary>
/// to set some of fields
/// </summary>
/// <param name="fields"> fields[i] == -1 means that i-th field is null; else i-th field = value[fields[i]</param>
/// <param name="value"> value of fields </param>
public void setSomeOfFields(int[] fields, string[] value)
{
_ticker = setField(0, fields, value);
_per = setField(1, fields, value);
_date = setField(2, fields, value);
_time = setField(3, fields, value);
_open = setField(4, fields, value);
_high = setField(5, fields, value);
_low = setField(6, fields, value);
_close = setField(7, fields, value);
_vol = setField(8, fields, value);
}

private string setField(int i, int[] fields, string[] value) => fields[i] == -1 ? null : value[fields[i]];


public void print()
{
Console.WriteLine($"ticker {valueToPrint(_ticker)}, per {valueToPrint(_per)}, date {valueToPrint(_date)}," +
$" time {valueToPrint(_time)}, open {valueToPrint(_open)}, high {valueToPrint(_high)}," +
$" low {valueToPrint(_low)}, close {valueToPrint(_close)}, vol {valueToPrint(_vol)}");
}

private string valueToPrint(string field) => field == null ? "null" : field;
}
}
17 changes: 17 additions & 0 deletions CoreDownloader/CoreDownloader/DataExample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<TICKER>,<PER>,<DATE>,<TIME>,<CLOSE>,<VOL>
EURUSD000TOD,W,20171106,0000,1.1638000,57132000
EURUSD000TOD,W,20171113,0000,1.1795500,28416000

<TICKER>,<PER>,<DATE>,<TIME>,<OPEN>,<HIGH>,<LOW>,<CLOSE>,<VOL>
POLY,1,20170620,100100,675.5000000,680.5000000,675.5000000,677.5000000,1603
POLY,1,20170620,100200,678.5000000,680.0000000,678.0000000,678.0000000,736
POLY,1,20170620,100300,678.0000000,679.5000000,678.0000000,679.0000000,56
POLY,1,20170620,100400,679.0000000,681.5000000,679.0000000,680.0000000,733
POLY,1,20170620,100500,680.0000000,681.5000000,680.0000000,681.5000000,198
POLY,1,20170620,100600,681.5000000,683.0000000,681.0000000,681.0000000,929
POLY,1,20170620,100700,681.5000000,681.5000000,681.5000000,681.5000000,100





168 changes: 168 additions & 0 deletions CoreDownloader/CoreDownloader/Downloader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FluentScheduler;

namespace CoreDownloader
{
public class Downloader
{
//private IQuoteStorage _storage { get; set; }
private MD5 md5Hash = MD5.Create();

volatile HashSet<string> hashUrls = new HashSet<string>();
private object _lockScedule = new object();
private object _lockHashes = new object();

public delegate void GetResponseDelegate(DownloadingResult downloadingResult);

private ScheduledJobRegistry _registry = new ScheduledJobRegistry();

public Downloader()
{
JobManager.Initialize(_registry);
}
// Added by Roma
private static Downloader _dwnl;
public static void Reqest(string path, GetResponseDelegate callback)
{
if (_dwnl == null)
_dwnl = new Downloader();
DownloadingTask downloadingTask = new DownloadingTask(path, 3000);
_dwnl.AddTask(downloadingTask, callback);
}

public void AddTask(DownloadingTask dTask, GetResponseDelegate callback)
{
string hash = GetMd5StringHash(dTask.url);
//if (!hashUrls.Contains(hash))
if (true) //because at the first time we could have not put the data
{
lock (_lockHashes)
{
hashUrls.Add(hash);
}
DownloadingResult dResult = new DownloadingResult();
dResult.name = hash;
lock (_lockScedule) // this one may be unneccessary, but idk how this scheduler works inside
{
JobManager.AddJob(() => DownloadAndPass(dTask, dResult),
schedule => schedule.WithName(hash).ToRunOnceIn(dTask.delay).Milliseconds());
}
JobManager.JobEnd += (info) =>
{
if (info.Name.Equals(hash))
{
callback(dResult);
}
};
}

}

/* make sure that seperator is ',' */
private void DownloadAndPass(DownloadingTask dTask, DownloadingResult dResult)
{
HttpClient httpClient = new HttpClient();
using (Stream resultStream = httpClient.GetStreamAsync(dTask.url).Result)
{
Validator val = new Validator();
val.Pass(resultStream, dResult);
// _storage.Pass(val.dataList);

/* just to check what has been passed */

foreach (Data value in val.dataList)
{
value.print();
}

// Added by Roma
dResult.dataList = val.dataList;
}
}



private void PassData(DownloadingResult dResult)
{
/*passing data to database*/
}

private bool ValidateData(Stream resultStream, DownloadingTask dTask, DownloadingResult dResult)
{
Console.WriteLine("Validating result");
/*some awesome validating methods, writind errors to dResult*/
int c;
/* writing result to a console just in testing and development purposes*/
do
{
c = resultStream.ReadByte();
Console.Write(Convert.ToChar(c));

} while (c != -1);
return true;
}

private string GetMd5StringHash(string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}

return sBuilder.ToString();
}

}


public class ScheduledJobRegistry : Registry
{
public ScheduledJobRegistry()
{
Console.WriteLine("Registry initialized");
/* Some initial jobs may be here */
}
}

public class DownloadingTask
{
public string url;

// public string result = String.Empty;
public int delay;

public DownloadingTask(string url, int delay)
{
this.url = url;
if (delay < 0)
{
this.delay = 0;
}
else
{
this.delay = delay;
}
}
}

/* holds result and errors happened to pass to the calling context*/
public class DownloadingResult
{
public string name;
public bool success = true;
public string error;
public List<Data> dataList;
}

}
42 changes: 42 additions & 0 deletions CoreDownloader/CoreDownloader/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using FluentScheduler;

namespace CoreDownloader
{
class Program
{
public static void Main(string[] args)
{
Downloader dwnl = new Downloader();
DownloadingTask downloadingTask = new DownloadingTask("http://export.finam.ru/export9.out/?market=45&em=182439&code=EURUSD000TOD&apply=0&df=1&" +
"mf=10&yf=2017&from=01.11.2017&dt=16&mt=10&yt=2017&" +
"to=16.11.2017&p=9&f=EURUSD000TOD_171101_171116&e=.txt&" +
"cn=EURUSD000TOD&dtf=1&tmf=2&MSOR=1&mstimever=0&sep=1&sep2=1&datf=3&at=1", 3000);
DownloadingTask downloadingTask2 = new DownloadingTask("http://export.finam.ru/export9.out/?market=45&em=182406&code=CNYRUB_TOM&apply=0&df=1&" +
"mf=10&yf=2017&from=01.11.2017&dt=16&mt=10&yt=2017&" +
"to=16.11.2017&p=9&f=CNYRUB_TOM_171101_171116&e=.txt&" +
"cn=CNYRUB_TOM&dtf=1&tmf=2&MSOR=1&mstimever=0&sep=1&sep2=1&datf=3&at=1", 1000);
dwnl.AddTask(downloadingTask, GetResponse);
dwnl.AddTask(downloadingTask2, GetResponse);
Console.Read();
}

public static void GetResponse(DownloadingResult downloadingResult)
{
if (downloadingResult.success)
{
Console.WriteLine("Task {0} succeeded", downloadingResult.name);
}
else
{
Console.WriteLine("Task {0} failed.\nError: {1}", downloadingResult.name, downloadingResult.error);
}
}

}
}
Loading