diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f9a257 --- /dev/null +++ b/.gitignore @@ -0,0 +1,342 @@ + +# Created by https://www.gitignore.io/api/visualstudio + +### VisualStudio ### +## 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/ +key.txt +config.json + +# 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/ +bin/ +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.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 personal settings +.cr/personal + +# 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/ + +# Local History for Visual Studio +.localhistory/ + + +# End of https://www.gitignore.io/api/visualstudio \ No newline at end of file diff --git a/BitBotBackToTheFuture.csproj b/BitBotBackToTheFuture.csproj new file mode 100644 index 0000000..810b366 --- /dev/null +++ b/BitBotBackToTheFuture.csproj @@ -0,0 +1,75 @@ + + + + Debug + AnyCPU + {46C3C22D-003D-4AD1-8DC3-B3B856C68F66} + Exe + BitBotBackToTheFuture + BitBotBackToTheFuture + v4.6.1 + + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + true + bin\Release + prompt + 4 + true + + + + + + + packages\Google.Protobuf.3.5.1\lib\net45\Google.Protobuf.dll + + + packages\MySql.Data.8.0.13\lib\net452\MySql.Data.dll + + + + + + + + + + + packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll + + + packages\TA-Lib.0.5.0.3\lib\TA-Lib-Core.dll + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BitBotBackToTheFuture.sln b/BitBotBackToTheFuture.sln new file mode 100644 index 0000000..229e088 --- /dev/null +++ b/BitBotBackToTheFuture.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2026 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BitBotBackToTheFuture", "BitBotBackToTheFuture.csproj", "{46C3C22D-003D-4AD1-8DC3-B3B856C68F66}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {46C3C22D-003D-4AD1-8DC3-B3B856C68F66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46C3C22D-003D-4AD1-8DC3-B3B856C68F66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46C3C22D-003D-4AD1-8DC3-B3B856C68F66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46C3C22D-003D-4AD1-8DC3-B3B856C68F66}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6AF64732-50F5-4A5A-9DB9-085D6FE8D721} + EndGlobalSection +EndGlobal diff --git a/BitMexAPI.cs b/BitMexAPI.cs new file mode 100644 index 0000000..462e5d4 --- /dev/null +++ b/BitMexAPI.cs @@ -0,0 +1,420 @@ +//using ServiceStack.Text; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Threading; + +namespace BitMEX +{ + public class OrderBookItem + { + public string Symbol { get; set; } + public int Level { get; set; } + public int BidSize { get; set; } + public decimal BidPrice { get; set; } + public int AskSize { get; set; } + public decimal AskPrice { get; set; } + public DateTime Timestamp { get; set; } + } + + public class BitMEXApi + { + private string domain = "https://testnet.bitmex.com"; + private string apiKey; + private string apiSecret; + private int rateLimit; + + public BitMEXApi(string bitmexKey = "", string bitmexSecret = "", string bitmexDomain = "", int rateLimit = 5000) + { + this.apiKey = bitmexKey; + this.apiSecret = bitmexSecret; + this.rateLimit = rateLimit; + this.domain = bitmexDomain; + } + + #region API Connector - Don't touch + private string BuildQueryData(Dictionary param) + { + if (param == null) + return ""; + + StringBuilder b = new StringBuilder(); + foreach (var item in param) + b.Append(string.Format("&{0}={1}", item.Key, WebUtility.UrlEncode(item.Value))); + + try { return b.ToString().Substring(1); } + catch (Exception) { return ""; } + } + + private string BuildJSON(Dictionary param) + { + if (param == null) + return ""; + + var entries = new List(); + foreach (var item in param) + entries.Add(string.Format("\"{0}\":\"{1}\"", item.Key, item.Value)); + + return "{" + string.Join(",", entries) + "}"; + } + + public static string ByteArrayToString(byte[] ba) + { + StringBuilder hex = new StringBuilder(ba.Length * 2); + foreach (byte b in ba) + hex.AppendFormat("{0:x2}", b); + return hex.ToString(); + } + + static object objLock = new object(); + private long GetNonce() + { + //lock (objLock) + { + System.Threading.Thread.Sleep(800); + DateTime yearBegin = new DateTime(2018, 1, 1); + return DateTime.UtcNow.Ticks - yearBegin.Ticks; + //long ret = long.Parse(DateTime.UtcNow.ToString("yyyyMMddHHmmssffff")); + //return ret; + } + + } + + private byte[] hmacsha256(byte[] keyByte, byte[] messageBytes) + { + using (var hash = new HMACSHA256(keyByte)) + { + return hash.ComputeHash(messageBytes); + } + } + + static object objLockQuery = new object(); + private string Query(string method, string function, Dictionary param = null, bool auth = false, bool json = false) + { + // lock (objLockQuery) + { + + String[] proxys = System.Text.RegularExpressions.Regex.Split(Http.get("https://www.proxy-list.download/api/v1/get?type=https&anon=elite&country=CN"), Environment.NewLine); + String proxy = proxys[new Random().Next(0, proxys.Length - 2)]; + + string paramData = json ? BuildJSON(param) : BuildQueryData(param); + string url = "/api/v1" + function + ((method == "GET" && paramData != "") ? "?" + paramData : ""); + string postData = (method != "GET") ? paramData : ""; + + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(domain + url); + webRequest.Method = method; + WebProxy webProxy = new WebProxy(proxy.Split(':')[0], int.Parse(proxy.Split(':')[1])); + //webRequest.Proxy = webProxy; + + if (auth) + { + string nonce = GetNonce().ToString(); + string message = method + url + nonce + postData; + byte[] signatureBytes = hmacsha256(Encoding.UTF8.GetBytes(apiSecret), Encoding.UTF8.GetBytes(message)); + string signatureString = ByteArrayToString(signatureBytes); + + webRequest.Headers.Add("api-nonce", nonce); + webRequest.Headers.Add("api-key", apiKey); + webRequest.Headers.Add("api-signature", signatureString); + } + + try + { + if (postData != "") + { + webRequest.ContentType = json ? "application/json" : "application/x-www-form-urlencoded"; + var data = Encoding.UTF8.GetBytes(postData); + using (var stream = webRequest.GetRequestStream()) + { + stream.Write(data, 0, data.Length); + } + } + + using (WebResponse webResponse = webRequest.GetResponse()) + using (Stream str = webResponse.GetResponseStream()) + using (StreamReader sr = new StreamReader(str)) + { + return sr.ReadToEnd(); + } + } + catch (WebException wex) + { + using (HttpWebResponse response = (HttpWebResponse)wex.Response) + { + if (response == null) + throw; + + using (Stream str = response.GetResponseStream()) + { + using (StreamReader sr = new StreamReader(str)) + { + return sr.ReadToEnd(); + } + } + } + } + } + } + #endregion + + #region Examples from BitMex + //public List GetOrderBook(string symbol, int depth) + //{ + // var param = new Dictionary(); + // param["symbol"] = symbol; + // param["depth"] = depth.ToString(); + // string res = Query("GET", "/orderBook", param); + // return JsonSerializer.DeserializeFromString>(res); + //} + + public string GetOrdersHistory(string Symbol,string timestamp) + { + var param = new Dictionary(); + param["symbol"] = Symbol; + param["timestamp"] = timestamp; + //param["columns"] = ""; + //param["count"] = 100.ToString(); + //param["start"] = 0.ToString(); + //param["reverse"] = false.ToString(); + //param["startTime"] = ""; + //param["endTime"] = ""; + return Query("GET", "/user/executionHistory", param, true); + } + + public string GetOrders(string Symbol) + { + var param = new Dictionary(); + param["symbol"] = Symbol; + param["filter"] = "{\"open\":true}"; + //param["columns"] = ""; + //param["count"] = 100.ToString(); + //param["start"] = 0.ToString(); + //param["reverse"] = false.ToString(); + //param["startTime"] = ""; + //param["endTime"] = ""; + return Query("GET", "/order", param, true); + } + + public string PostOrders() + { + var param = new Dictionary(); + param["symbol"] = "XBTUSD"; + param["side"] = "Buy"; + param["orderQty"] = "1"; + param["ordType"] = "Market"; + return Query("POST", "/order", param, true); + } + + public string DeleteOrders(String id) + { + var param = new Dictionary(); + param["orderID"] = id; + param["text"] = "cancel order by ID"; + return Query("DELETE", "/order", param, true, true); + } + #endregion + + #region Our Calls + public List GetOrderBook(string symbol, int depth) + { + var param = new Dictionary(); + param["symbol"] = symbol; + param["depth"] = depth.ToString(); + string res = Query("GET", "/orderBook/L2", param); + return JsonConvert.DeserializeObject>(res); + } + + public string PostOrderPostOnly(string Symbol, string Side, double Price, int Quantity, bool force = false) + { + var param = new Dictionary(); + param["symbol"] = Symbol; + param["side"] = Side; + param["orderQty"] = Quantity.ToString(); + param["ordType"] = "Limit"; + if (!force) + param["execInst"] = "ParticipateDoNotInitiate"; + //param["displayQty"] = 1.ToString(); // Shows the order as hidden, keeps us from moving price away from our own orders + param["price"] = Price.ToString().Replace(",", "."); + string ret = Query("POST", "/order", param, true); + + return ret; + } + + public string MarketOrder(string Symbol, string Side, int Quantity) + { + var param = new Dictionary(); + param["symbol"] = Symbol; + param["side"] = Side; + param["orderQty"] = Quantity.ToString(); + param["ordType"] = "Market"; + String ret = Query("POST", "/order", param, true); + + + + return ret; + + + } + + public string CancelAllOpenOrders(string symbol, string Note = "") + { + var param = new Dictionary(); + param["symbol"] = symbol; + param["text"] = Note; + return Query("DELETE", "/order/all", param, true, true); + } + + public List GetActiveInstruments() + { + string res = Query("GET", "/instrument/active"); + return JsonConvert.DeserializeObject>(res); + } + + public List GetInstrument(string symbol) + { + var param = new Dictionary(); + param["symbol"] = symbol; + string res = Query("GET", "/instrument", param); + return JsonConvert.DeserializeObject>(res); + } + + public List GetCandleHistory(string symbol, int count, string size) + { + var param = new Dictionary(); + param["symbol"] = symbol; + param["count"] = count.ToString(); + param["reverse"] = true.ToString(); + param["partial"] = "false"; + param["binSize"] = size; + string res = Query("GET", "/trade/bucketed", param); + return JsonConvert.DeserializeObject>(res).OrderByDescending(a => a.TimeStamp).ToList(); + } + + public List GetOpenPositions(string symbol) + { + var param = new Dictionary(); + string res = Query("GET", "/position", param, true); + return JsonConvert.DeserializeObject>(res).Where(a => a.Symbol == symbol && a.IsOpen == true).OrderByDescending(a => a.TimeStamp).ToList(); + } + + public List GetOpenOrders(string symbol) + { + var param = new Dictionary(); + param["symbol"] = symbol; + param["reverse"] = true.ToString(); + string res = Query("GET", "/order", param, true); + return JsonConvert.DeserializeObject>(res).Where(a => a.OrdStatus == "New" || a.OrdStatus == "PartiallyFilled").OrderByDescending(a => a.TimeStamp).ToList(); + } + + public string EditOrderPrice(string OrderId, double Price) + { + var param = new Dictionary(); + param["orderID"] = OrderId; + param["price"] = Price.ToString(); + return Query("PUT", "/order", param, true, true); + } + + public string GetWallet() + { + var param = new Dictionary(); + param["currency"] = "XBt"; + return Query("GET", "/user/walletHistory", param, true); + } + + + + #endregion + + + + #region RateLimiter + + private long lastTicks = 0; + private object thisLock = new object(); + + private void RateLimit() + { + lock (thisLock) + { + long elapsedTicks = DateTime.Now.Ticks - lastTicks; + var timespan = new TimeSpan(elapsedTicks); + if (timespan.TotalMilliseconds < rateLimit) + Thread.Sleep(rateLimit - (int)timespan.TotalMilliseconds); + lastTicks = DateTime.Now.Ticks; + } + } + + #endregion RateLimiter + } + + // Working Classes + public class OrderBook + { + public string Side { get; set; } + public double Price { get; set; } + public int Size { get; set; } + } + + public class Instrument + { + public string Symbol { get; set; } + public double TickSize { get; set; } + public double Volume24H { get; set; } + } + + public class Candle + { + public DateTime TimeStamp { get; set; } + public double? open { get; set; } + public double? close { get; set; } + public double? high { get; set; } + public double? low { get; set; } + public double? volume { get; set; } + } + + public class Position + { + public DateTime TimeStamp { get; set; } + public double? Leverage { get; set; } + public int? CurrentQty { get; set; } + public double? CurrentCost { get; set; } + public bool IsOpen { get; set; } + public double? MarkPrice { get; set; } + public double? MarkValue { get; set; } + public double? UnrealisedPnl { get; set; } + public double? UnrealisedPnlPcnt { get; set; } + public double? AvgEntryPrice { get; set; } + public double? BreakEvenPrice { get; set; } + public double? LiquidationPrice { get; set; } + public double? LastValue { get; set; } + + public string Symbol { get; set; } + + public double percentual() + { + if (UnrealisedPnl < 0) + return (((((double)UnrealisedPnl * (-1)) * 100) / (double)LastValue) * (double)Leverage) * (-1); + else + return ((((double)UnrealisedPnl) * 100) / (double)LastValue) * (double)Leverage; + } + + } + + public class Order + { + public DateTime TimeStamp { get; set; } + public string Symbol { get; set; } + public string OrdStatus { get; set; } + public string OrdType { get; set; } + public string OrderId { get; set; } + public string Side { get; set; } + public double? Price { get; set; } + public int? OrderQty { get; set; } + public int? DisplayQty { get; set; } + } +} \ No newline at end of file diff --git a/Database.cs b/Database.cs new file mode 100644 index 0000000..9c521b0 --- /dev/null +++ b/Database.cs @@ -0,0 +1,92 @@ +using BitBotBackToTheFuture; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +public class Database +{ + + //private static string dataBaseFile = MainClass.location + "bd.xml"; + public static void captureDataJob() + { + while (true) + { + try + { + captureData(); + } + catch + { + + } + System.Threading.Thread.Sleep(MainClass.intervalCapture); + } + } + + public static void captureData() + { + lock (MainClass.data) + { + string dataBaseFile = MainClass.location + "bd.xml"; + try + { + System.Data.DataSet ds = null; + bool create = false; + if (!System.IO.File.Exists(dataBaseFile)) + { + System.Data.DataTable dt = new System.Data.DataTable("Balances"); + dt.Columns.Add("Date"); + dt.Columns.Add("Coin"); + dt.Columns.Add("Amount"); + + dt.Rows.Add("", "", ""); + + System.Data.DataTable dtParameters = new System.Data.DataTable("Parameters"); + dtParameters.Columns.Add("Parameter"); + dtParameters.Columns.Add("Value"); + dtParameters.Rows.Add("", ""); + + + ds = new System.Data.DataSet(); + ds.DataSetName = "Database"; + ds.Tables.Add(dt); + ds.Tables.Add(dtParameters); + ds.WriteXml(dataBaseFile); + create = true; + } + + ds = new System.Data.DataSet(); + ds.ReadXml(dataBaseFile); + + BitMEX.BitMEXApi bitMEXApi = new BitMEX.BitMEXApi(MainClass.bitmexKey, MainClass.bitmexSecret, MainClass.bitmexDomain); + string json = bitMEXApi.GetWallet(); + JContainer jCointaner = (JContainer)JsonConvert.DeserializeObject(json, (typeof(JContainer))); + + + //ClassDB.execS(ClassDB.dbquery.Replace("@balance", jCointaner[0]["walletBalance"].ToString().Replace(",", "."))); + + if (create) + ds.Tables[0].Rows.Clear(); + + ds.Tables[0].Rows.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), MainClass.pair, jCointaner[0]["walletBalance"].ToString()); + + ds.Tables[1].Rows.Clear(); + ds.Tables[1].Rows.Add("OpenOrders", bitMEXApi.GetOpenOrders(MainClass.pair).Count); + ds.Tables[1].Rows.Add("Amount", jCointaner[0]["walletBalance"].ToString()); + + + System.IO.File.Delete(dataBaseFile); + ds.WriteXml(dataBaseFile); + + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + } +} diff --git a/Http.cs b/Http.cs new file mode 100644 index 0000000..3196925 --- /dev/null +++ b/Http.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Net.Security; + +public static class Http +{ + + public static string postGeneric(String url, String parameters) + { + try + { + // lock (objLock) + { + + var request = (HttpWebRequest)WebRequest.Create(url); + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + var data = Encoding.ASCII.GetBytes(parameters); + request.Method = "POST"; + request.ContentType = "application/x-www-form-urlencoded"; + request.ContentLength = data.Length; + using (var stream = request.GetRequestStream()) + { + stream.Write(data, 0, data.Length); + } + var response = (HttpWebResponse)request.GetResponse(); + String result = new StreamReader(response.GetResponseStream()).ReadToEnd(); + + + return result; + } + } + catch (Exception ex) + { + + return null; + } + finally + { + + } + } + public static string get(String url) + { + try + { + + String r = ""; + ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + var httpWebRequest = (HttpWebRequest)WebRequest.Create(new Uri(url)); + httpWebRequest.Method = "GET"; + var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); + var responseStream = httpWebResponse.GetResponseStream(); + if (responseStream != null) + { + var streamReader = new StreamReader(responseStream); + r = streamReader.ReadToEnd(); + } + if (responseStream != null) responseStream.Close(); + //Console.WriteLine(r); + return r; + } + catch (WebException ex) + { + return null; + } + } + +} \ No newline at end of file diff --git a/LogClass.cs b/LogClass.cs new file mode 100644 index 0000000..bd6a330 --- /dev/null +++ b/LogClass.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BitBotBackToTheFuture +{ + static class LogClass + { + + + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..9675c57 --- /dev/null +++ b/Program.cs @@ -0,0 +1,234 @@ +using BitBotBackToTheFuture; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +enum TendencyMarket +{ + HIGH, + NORMAL, + LOW, + VERY_LOW, + VERY_HIGH +} + +class MainClass +{ + + + //REAL NET + public static string version = "0.0.2.14"; + public static string location = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + System.IO.Path.DirectorySeparatorChar; + + public static string bitmexKey = ""; + public static string bitmexSecret = ""; + public static string bitmexKeyWeb = ""; + public static string bitmexSecretWeb = ""; + public static string pair = ""; + public static int qtdyContacts = 0; + public static int interval = 0; + public static int intervalOrder = 0; + public static int intervalCapture = 0; + public static int intervalCancelOrder = 30; + public static int positionContracts = 0; + public static double profit = 0; + public static string bitmexDomain = ""; + + + public static BitMEX.BitMEXApi bitMEXApi = null; + + + + + + public static Object data = new Object(); + + + public static void Main(string[] args) + { + try + { + Console.Title = "Loading..."; + + Console.ForegroundColor = ConsoleColor.White; + + log("Deleron - Back to the future - v" + version + " - Bitmex version"); + log("by Matheus Grijo ", ConsoleColor.Green); + + log("GITHUB http://github.com/matheusgrijo", ConsoleColor.Blue); + log("Load config..."); + + String jsonConfig = System.IO.File.ReadAllText(location + "key.txt"); + JContainer jCointaner = (JContainer)JsonConvert.DeserializeObject(jsonConfig, (typeof(JContainer))); + + + bitmexKey = jCointaner["key"].ToString(); + bitmexSecret = jCointaner["secret"].ToString(); + bitmexKeyWeb = jCointaner["webserverKey"].ToString(); + bitmexSecretWeb = jCointaner["webserverSecret"].ToString(); + bitmexDomain = jCointaner["domain"].ToString(); + pair = jCointaner["pair"].ToString(); + qtdyContacts = int.Parse(jCointaner["contract"].ToString()); + interval = int.Parse(jCointaner["interval"].ToString()); + intervalCapture = int.Parse(jCointaner["webserverIntervalCapture"].ToString()); + + + + bitMEXApi = new BitMEX.BitMEXApi(bitmexKey, bitmexSecret, bitmexDomain); + + + + if (jCointaner["webserver"].ToString() == "enable") + { + WebServer ws = new WebServer(WebServer.SendResponse, jCointaner["webserverConfig"].ToString()); + ws.Run(); + System.Threading.Thread tCapture = new Thread(Database.captureDataJob); + tCapture.Start(); + System.Threading.Thread.Sleep(1000); + OperatingSystem os = Environment.OSVersion; + PlatformID pid = os.Platform; + if (pid != PlatformID.Unix) + { + System.Diagnostics.Process.Start(jCointaner["webserverConfig"].ToString()); + } + } + + + + log("Total open orders: " + bitMEXApi.GetOpenOrders(pair).Count); + + log(""); + log("Wallet: " + bitMEXApi.GetWallet()); + + + + string codeTendency = ""; + + //LOOP + while (true) + { + + try + { + + + + //Surf mode + + + + + String json = Http.get("https://anubis.website/api/anubis/trend/"); + JContainer jTrrend = (JContainer)JsonConvert.DeserializeObject(json, (typeof(JContainer))); + + int open = getPosition(); + + //OPEN LONG + if (jTrrend["data"][1]["trend"].ToString() == "SHORT" && jTrrend["data"][0]["trend"].ToString() == "LONG" && jTrrend["data"][0]["timestamp"].ToString() != codeTendency) + { + if (open < 0) + open = Math.Abs(open); + + codeTendency = jTrrend["data"][0]["timestamp"].ToString(); + bitMEXApi.MarketOrder(pair, "Buy", qtdyContacts + open); + + } + + //OPEN SHORT + if (jTrrend["data"][1]["trend"].ToString() == "LONG" && jTrrend["data"][0]["trend"].ToString() == "SHORT" && jTrrend["data"][0]["timestamp"].ToString() != codeTendency) + { + codeTendency = jTrrend["data"][0]["timestamp"].ToString(); + bitMEXApi.MarketOrder(pair, "Sell", qtdyContacts + open); + } + + log("wait " + interval + "ms", ConsoleColor.White); + Thread.Sleep(interval); + + + } + catch (Exception ex) + { + log("while true::" + ex.Message + ex.StackTrace); + } + + + } + + } + catch (Exception ex) + { + log("ERROR FATAL::" + ex.Message + ex.StackTrace); + } + } + + + + + //By Lucas Sousa modify MatheusGrijo + static int getPosition() + { + try + { + log("getPosition..."); + List OpenPositions = bitMEXApi.GetOpenPositions(pair); + int _qtdContacts = 0; + foreach (var Position in OpenPositions) + _qtdContacts += (int)Position.CurrentQty; + log("getPosition: " + _qtdContacts); + return _qtdContacts; + } + catch (Exception ex) + { + log("getPosition::" + ex.Message + ex.StackTrace); + throw new Exception("Error getPosition"); + } + } + + + static string getValue(String nameList, String nameIndicator, String nameParameter) + { + String jsonConfig = System.IO.File.ReadAllText(location + "key.txt"); + JContainer jCointaner = (JContainer)JsonConvert.DeserializeObject(jsonConfig, (typeof(JContainer))); + foreach (var item in jCointaner[nameList]) + if (item["name"].ToString().Trim().ToUpper() == nameIndicator.ToUpper().Trim()) + return item[nameParameter].ToString().Trim(); + return null; + } + + public static void log(string value, ConsoleColor color = ConsoleColor.White) + { + try + { + + value = "[" + DateTime.Now.ToString() + "] - " + value; + Console.ForegroundColor = color; + Console.WriteLine(value); + Console.ForegroundColor = ConsoleColor.White; + + System.IO.StreamWriter w = new StreamWriter(location + DateTime.Now.ToString("yyyyMMdd") + "_log.txt", true); + w.WriteLine(value); + w.Close(); + w.Dispose(); + + } + catch { } + } + + + + +} + + + + + diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f22be1a --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("BitBotBackToTheFuture")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/README.md b/README.md new file mode 100644 index 0000000..a478d43 --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# BitBotBackToTheFuture +Bot of Bitmax + +Example file "key.txt" (Configuration) + +{ + +"key":"", + +"secret":"", + +"domain":"https://testnet.bitmex.com", + +"pair":"XBTUSD", + +"contract":300, + +"profit":0.2, + +"fee":0.075, + +"long":"enable", + +"short":"enable", + +"interval":2000, + +"intervalOrder":60000, + +"timeGraph":"1m", + + +"webserver":"enable", + +"webserverConfig":"http://localhost:5321/bot/", + +"webserverIntervalCapture":300000, + +"webserverKey":"", + +"webserverSecret":"", + + +"indicatorsEntry":[ + + { + +"name":"CCI", + + "period":8 + }, + { + +"name":"RSI", + + "period":8 + }, + { + +"name":"BBANDS", + + "period":7 + } +], + + + +"indicatorsEntryCross":[ + + + { + +"name":"MA", + + "period":5 + } + + +], + +"indicatorsEntryDecision":[ + + + { + +"name":"RSI", + + "period":8, + "decision":"enable", + "decisionPoint":40, + "tendency":"enable" + } + + + ] + + +} + + +DONATE + +BTC 39DWjHHGXJh9q82ZrxkA8fiZoE37wL8jgh + +BCH qqzwkd4klrfafwvl7ru7p7wpyt5z3sjk6y909xq0qk + +ETH 0x3017E79f460023435ccD285Ff30Bd10834D20777 + +ETC 0x088E7E67af94293DB55D61c7B55E2B098d2258D9 + +LTC MVT8fxU4WBzdfH5XgvRPWkp7pE4UyzG9G5 diff --git a/WebServer.cs b/WebServer.cs new file mode 100644 index 0000000..22ad380 --- /dev/null +++ b/WebServer.cs @@ -0,0 +1,173 @@ +using System; +using System.Net; +using System.Threading; +using System.Linq; +using System.Text; +using BitBotBackToTheFuture; + +public class WebServer +{ + + + public static string SendResponse(HttpListenerRequest request) + { + lock (MainClass.data) + { + try + { + System.Data.DataSet ds = new System.Data.DataSet(); + ds.ReadXml(MainClass.location + "bd.xml"); + + StringBuilder sb = new StringBuilder(); + + + sb.AppendLine(System.IO.File.ReadAllText(MainClass.location + "header.html") ); + + + double perc = 0; + try { perc = ((double.Parse(ds.Tables[0].Rows[ds.Tables[0].Rows.Count - 1][2].ToString()) * 100) / double.Parse(ds.Tables[0].Rows[0][2].ToString())) - 100; } + catch { } + sb.AppendLine("
Status: running
"); + sb.AppendLine("Version: " + MainClass.version + "
"); + sb.AppendLine("Site: " + MainClass.bitmexDomain + "
"); + sb.AppendLine("Last update: " + DateTime.Now.ToString() + "
"); + sb.AppendLine("Amount: " + ds.Tables[1].Rows[1]["Value"].ToString() + "
"); + sb.AppendLine("Open position: " + MainClass.positionContracts.ToString() + "
"); + sb.AppendLine("Amount: " + ds.Tables[1].Rows[1]["Value"].ToString() + " (" + double.Parse(ds.Tables[1].Rows[1]["Value"].ToString()) / 100000000 + " BTC)
"); + sb.AppendLine("

Profit: " + perc + "%

"); + sb.AppendLine("Qty contracts: " + MainClass.qtdyContacts.ToString() + "
"); + + try + { + + String graph = ""; + + for (int i = 0; i < ds.Tables[0].Rows.Count; i++) + { + graph += "['" + ds.Tables[0].Rows[i][0].ToString() + "'," + ds.Tables[0].Rows[i][2].ToString() + "],"; + } + + + + graph = graph.Substring(0, graph.Length - 1); + + + + + + sb.Append("
"); + } + catch + { } + + + + + sb.AppendLine(System.IO.File.ReadAllText(MainClass.location + "footer.html")); + + sb.AppendLine(""); + + return sb.ToString(); + } + catch (Exception ex) + { + + return ""; + + } + } + } + + private readonly HttpListener _listener = new HttpListener(); + private readonly Func _responderMethod; + + public WebServer(string[] prefixes, Func method) + { + if (!HttpListener.IsSupported) + throw new NotSupportedException( + "Needs Windows XP SP2, Server 2003 or later."); + + // URI prefixes are required, for example + // "http://localhost:8080/index/". + if (prefixes == null || prefixes.Length == 0) + throw new ArgumentException("prefixes"); + + // A responder method is required + if (method == null) + throw new ArgumentException("method"); + + foreach (string s in prefixes) + _listener.Prefixes.Add(s); + + _responderMethod = method; + _listener.Start(); + } + + public WebServer(Func method, params string[] prefixes) + : this(prefixes, method) { } + + public void Run() + { + ThreadPool.QueueUserWorkItem((o) => + { + Console.WriteLine("Webserver running..."); + try + { + while (_listener.IsListening) + { + ThreadPool.QueueUserWorkItem((c) => + { + var ctx = c as HttpListenerContext; + try + { + string rstr = _responderMethod(ctx.Request); + byte[] buf = Encoding.UTF8.GetBytes(rstr); + ctx.Response.ContentLength64 = buf.Length; + ctx.Response.OutputStream.Write(buf, 0, buf.Length); + } + catch { } // suppress any exceptions + finally + { + // always close the stream + ctx.Response.OutputStream.Close(); + } + }, _listener.GetContext()); + } + } + catch { } // suppress any exceptions + }); + } + + public void Stop() + { + _listener.Stop(); + _listener.Close(); + } +} diff --git a/app.config b/app.config new file mode 100644 index 0000000..884f984 --- /dev/null +++ b/app.config @@ -0,0 +1,3 @@ + + + diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..659bb86 --- /dev/null +++ b/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file