commit bf1b64db7dc6fe5dff302bce46af8f0f6ff75cc7 Author: Harald Wolff Date: Thu Nov 23 13:00:44 2017 +0100 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e82d27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Autosave files +*~ + +# build +[Oo]bj/ +[Bb]in/ +packages/ +TestResults/ + +# globs +Makefile.in +*.DS_Store +*.sln.cache +*.suo +*.cache +*.pidb +*.userprefs +*.usertasks +config.log +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.user +*.tar.gz +tarballs/ +test-results/ +Thumbs.db + +# Mac bundle stuff +*.dmg +*.app + +# resharper +*_Resharper.* +*.Resharper + +# dotCover +*.dotCover diff --git a/BotManager.cs b/BotManager.cs new file mode 100644 index 0000000..a36e1e7 --- /dev/null +++ b/BotManager.cs @@ -0,0 +1,370 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using sharp.tradebot; +using sharp.json; +using sharp.json.attributes; +using System.Threading.Tasks; +using System.IO; +using System.Text; +using sharp.trading.logging; +using sharp.trading; +using System.Runtime.CompilerServices; +using System.Runtime.Remoting; + +namespace TradeBot +{ + public class BotManager + { + public TradingBotEnvironment BotEnvironment { get; private set; } + public String DataBaseFile { get; private set; } + + + List instances = new List(); + + public BotManager(string baseDirectory) + { + DataBaseFile = Path.Combine(baseDirectory, "botmanager.json"); + BotEnvironment = new TradingBotEnvironment(TradingEnvironment.DefaultConnection, baseDirectory); + + if (!Directory.Exists(Path.Combine(BotEnvironment.BaseDataDirectory, "logs"))){ + Directory.CreateDirectory(Path.Combine(BotEnvironment.BaseDataDirectory, "logs")); + } + + load(); + } + + private void load() + { + TradingBotInstance[] _instances = JSON.ReadFrom(DataBaseFile,new TradingBotInstance[0]).To(); + if (_instances != null) + { + instances.AddRange(_instances); + } + } + + private void save() + { + lock (this) + { + JSON.From(instances.ToArray()).WriteTo(DataBaseFile, true); + } + } + + public void Save() + { + save(); + } + + public Guid RegisterBot(string DllPath, string ClassName) + { + Guid guid = Guid.NewGuid(); + lock (this) + { + RegisterBot(DllPath, ClassName, guid); + } + return guid; + } + public void RegisterBot(string DllPath, string ClassName, Guid uid) + { + TradingBotInstance i = new TradingBotInstance(); + i.DllPath = DllPath; + i.ClassName = ClassName; + i.UID = uid; + lock (this) + { + this.instances.Add(i); + Save(); + } + } + + public void UnregisterBot(Guid guid) + { + lock (this) + { + foreach (TradingBotInstance inst in instances) + { + if (inst.UID.Equals(guid)) + { + UnloadBot(inst); + break; + } + } + } + } + + + + public void LoadBot(String uid){ + LoadBot(findBot(Guid.Parse(uid))); + } + public void UnloadBot(String uid) + { + UnloadBot(findBot(Guid.Parse(uid))); + } + + public void LoadBot(Guid uid) + { + LoadBot(findBot(uid)); + } + public void UnloadBot(Guid uid) + { + UnloadBot(findBot(uid)); + } + + public void LoadBotAndPrepare(Guid uid) + { + LoadBotAndPrepare(findBot(uid)); + } + + + public void LoadBotAndPrepare(TradingBotInstance bot) + { + bot.Load(BotEnvironment); + bot.Prepare(); + } + + public void LoadBot(TradingBotInstance bot) + { + bot.Load(BotEnvironment); + } + public void UnloadBot(TradingBotInstance bot) + { + bot.Unload(); + } + + public void LoadAllBots(){ + foreach (TradingBotInstance bot in instances){ + bot.Load(BotEnvironment); + } + } + + public TradingBotInstance[] RegisteredBots{ + get { return this.instances.ToArray(); } + } + + private TradingBotInstance findBot(Guid uid){ + foreach (TradingBotInstance inst in instances){ + if (inst.UID.Equals(uid)){ + return inst; + } + } + return null; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("[BotManager Dump]"); + foreach (TradingBotInstance i in instances) + { + sb.AppendLine(i.ToString()); + } + return sb.ToString(); + } + } + + [JSONClassPolicy(Policy = JSONPolicy.ATTRIBUTED)] + public class TradingBotInstance : MarshalByRefObject + { + [JSONField] + public String DllPath { get; set; } + [JSONField] + public String ClassName { get; set; } + [JSONField] + public Guid UID { get; set; } + + private AppDomain _appDomain; + private Assembly _assembly; + private TradeBotLoader loader; + private TradingBot _instance; + private Logger _logger; + + /* + + public void Load(TradingBotEnvironment environment) + { + AppDomainSetup ads = new AppDomainSetup(); + // ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + + this._appDomain = AppDomain.CreateDomain(String.Format("TradeBotLoader:{0}:{1}", UID, Guid.NewGuid().ToString()), AppDomain.CurrentDomain.Evidence, ads); + this.loader = (TradeBotLoader)this._appDomain.CreateInstanceFromAndUnwrap("sharp.tradebot.dll", "sharp.tradebot.TradeBotLoader"); + this.loader.DllPath = DllPath; + this.loader.ClassName = ClassName; + this.loader.UID = UID; + + this.loader.Load(environment); + } + + public void Unload() + { + if (this.loader != null){ + this.loader.Unload(); + } + AppDomain.Unload(this._appDomain); + this._appDomain = null; + this.loader = null; + } + + public void Prepare() + { + if (this.loader != null){ + this.loader.Prepare(); + } + } + + public void Unprepare() + { + if (this.loader != null){ + this.loader.Unprepare(); + } + } + + + + */ + + public void Load(TradingBotEnvironment environment) + { + //AppDomainSetup ads = new AppDomainSetup(); + // ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + + //this._appDomain = AppDomain.CreateDomain(String.Format("{0}:{1}:{2}:{3}", DllPath, ClassName, UID, Guid.NewGuid().ToString()), AppDomain.CurrentDomain.Evidence, ads); + //this._instance = (TradingBot)this._appDomain.CreateInstanceFromAndUnwrap(DllPath, ClassName); + this._instance = (TradingBot)Activator.CreateInstanceFrom(DllPath, ClassName).Unwrap(); + this._logger = new FileLogger(Path.Combine(environment.BaseDataDirectory, "logs", String.Format("{0}.log", UID.ToString()))); + this._instance.AfterLoad(environment, UID, this._logger,null); + } + + public void Unload() + { + if (this._instance != null) + { + lock (this._instance) + { + if (this._instance.IsPrepared) + { + this._instance.Unprepare(); + } + this._logger.Close(); + this._logger = null; + } + this._instance = null; + //AppDomain.Unload(this._appDomain); + this._appDomain = null; + } + } + + public void Prepare() + { + if (this._instance != null) + { + lock (this._instance) + { + this._instance.Prepare(); + } + } + } + + public void Unprepare() + { + if (this._instance != null) + { + lock (this._instance) + { + this._instance.Unprepare(); + } + } + } + } +} +/** + * + [JSONClassPolicy(Policy = JSONPolicy.ATTRIBUTED)] + public class BotDll + { + [JSONField] + public string FileName { get; private set;} + + private AppDomain appDomain; + private Assembly assembly; + + public Type[] BotClasses { get; private set; } + + public BotDll(string filename){ + FileName = filename; + } + + public void Load(){ + if (appDomain == null){ + AppDomainSetup ads = new AppDomainSetup(); + ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + + this.appDomain = AppDomain.CreateDomain(FileName,AppDomain.CurrentDomain.Evidence,ads); + + //this.assembly = this.appDomain.Load(FileName); + + try { + TradingBot bot = (TradingBot)this.appDomain.CreateInstanceFromAndUnwrap(FileName, "BigBot.BigBot"); + } catch (Exception e){ + Console.WriteLine(e); + } + + Scan(); + } else { + throw new InvalidOperationException("BotDll already loaded."); + } + } + + public void Unload(){ + if (appDomain != null){ + + AppDomain.Unload(appDomain); + + BotClasses = null; + assembly = null; + appDomain = null; + + } else { + throw new InvalidOperationException("BotDll is not loaded."); + } + } + + private void Scan(){ + List botclasses = new List(); + + Console.WriteLine("Scanning...."); + + foreach (Type t in this.assembly.ExportedTypes){ + if (t.IsSubclassOf(typeof(TradingBot))){ + Console.WriteLine("Found BotClass: {0}", t.Name); + botclasses.Add(t); + } else { + Console.WriteLine(" No BotClass: {0}", t.Name); + } + } + + BotClasses = botclasses.ToArray(); + } + } + + [JSONClassPolicy(Policy = JSONPolicy.ATTRIBUTED)] + public class BotInstance + { + [JSONField] + public String ClassName { get; private set; } + [JSONField] + public String InstanceUID { get; private set; } + + public BotDll Dll { get; set; } + + public BotInstance(){ + InstanceUID = Guid.NewGuid().ToString(); + } + + + } + +} +**/ + diff --git a/BotSpecification.cs b/BotSpecification.cs new file mode 100644 index 0000000..1c707a6 --- /dev/null +++ b/BotSpecification.cs @@ -0,0 +1,69 @@ +using System; +using System.Reflection; +using sharp.tradebot; + +namespace TradeBot +{ + public class BotSpecification : MarshalByRefObject + { + public string DllPath { get; private set; } + public string ClassName { get; private set; } + public object[] Arguments { get; private set; } + + public string BotSpec { get { return string.Format("{0}:{1}",ClassName,DllPath); } } + + public bool IsLoaded + { + get + { + return currentInstance != null; + } + } + public TradingBot CurrentInstance + { + get { + return this.currentInstance; + } + } + + AppDomain Domain; + Assembly Assembly; + Type ClassType; + + TradingBot currentInstance; + + public BotSpecification(string dllpath,string className,object[] arguments) + { + DllPath = dllpath; + ClassName = className; + } + + public void Unload(){ + currentInstance = null; + ClassType = null; + Assembly = null; + AppDomain.Unload(Domain); + Domain = null; + } + public void Load(){ + if (Domain != null){ + Unload(); + } + + Domain = AppDomain.CreateDomain(DllPath); + Assembly = Domain.Load(DllPath); + ClassType = Assembly.GetType(ClassName); + } + + TradingBot TradingBot { + get + { + if (currentInstance == null){ + currentInstance = (TradingBot)Activator.CreateInstance(ClassType); + } + return currentInstance; + } + } + + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..89c558e --- /dev/null +++ b/Program.cs @@ -0,0 +1,399 @@ +using System; +using sharp.trading.bittrex; +using sharp.extensions; +using sharp.trading; +using System.Collections.Generic; +using sharp.json; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.IO; +using System.Linq; +using System.Threading; +using System.Text; +using System.Diagnostics; +using System.Collections; +using System.CodeDom; +using sharp.trading.cache; +using sharp.json.network; +using sharp.tradebot.rpc; +using System.Net.WebSockets; +using TradeBot; +using System.Net.Sockets; + + +/** + * tradebot.exe [ --test ] --servicedaemon [ --port ] + * --newbot [ --dll ] --class + * --unload + * --load + * + **/ + + +namespace sharp.tradebot +{ + class TradeBotApplication + { + public static int jsonPort = 33555; + + public static void Main(string[] args) + { + ArgumentReader ar = new ArgumentReader(args); + + while (ar.MoveNext()) + { + switch (ar.Current) + { + case "--test": + TradingEnvironment.DataDirectory = "sharp.trading.data"; + jsonPort = 33554; + break; + case "--servicedaemon": + ServiceDaemon.Run(ar.Reminder()); + return; + case "--shutdown": + ShutDown(); + return; + case "--register": + callDaemon("register", ar.NextFollowing(3)); + return; + case "--unregister": + callDaemon("unregister", ar.NextFollowing(1)); + return; + case "--load": + callDaemon("load", ar.NextFollowing(1)); + return; + case "--unload": + callDaemon("unload", ar.NextFollowing(1)); + return; + case "--reload": + callDaemon("reload", ar.NextFollowing(1)); + return; + + + } + } + } + + private static void ShutDown(){ + callDaemon("shutdown",new string[0]); + } + + + private static bool callDaemon(string command,string[] arguments){ + RPCRequest request = new RPCRequest(); + request.Command = command; + request.Arguments = arguments; + + JSONTcpClient client = new JSONTcpClient(jsonPort); + client.Send(JSON.From(request)); + + JSON jresponse = client.Receive(); + RPCResponse response = jresponse.To(); + Console.WriteLine("callDaemon: Daemon Message: {0}",response.Message); + + request = new RPCRequest(); + request.Arguments = new string[0]; + request.Command = "disconnect"; + client.Send(JSON.From(request)); + + return response.Success; + } + + + + + + + + + + + + + + +//TradeBotApplication app = new TradeBotApplication(); +//app.Initialize(args); +//app.Prepare(); + +//try +//{ +// IEnumerator ae = app.Arguments.ToArray().GetEnumerator(); +// while (ae.MoveNext()) +// { +// switch (ae.Current.ToString()) +// { +// case "-test": +// app.Arguments.Remove(ae.Current.ToString()); +// jsonPort = 33554; +// break; +// case "-servicedaemon": +// app.Mode = AppMode.SERVICEDAEMON; +// app.Arguments.Remove(ae.Current.ToString()); +// break; +// } +// } +//} catch (Exception e){ +// Console.WriteLine("Exception while handling command line arguments. {0}",e.ToString()); +// app.LockFile.Unlock(); +// return; +//} + + +//app.Start(); +//app.Shutdown(); + + + + + + //public enum AppMode { + // DEFAULT, SERVICEDAEMON + //} + + //public LockFile LockFile { get; private set; } + + //public AppMode Mode { get; set; } = AppMode.DEFAULT; + + //List tradingBots = new List(); + + //List Arguments = new List(); + + //public TradeBotApplication() + //{ + // this.LockFile = new LockFile(getLockFileName()); + //} + + //public string getLockFileName(){ + // return Path.Combine(TradingBotEnvironment.BaseDataDirectory, "tradebot.lock"); + //} + + //private void Initialize(string[] arguments) + //{ + // this.Arguments.AddRange(arguments); + + // if (TradingEnvironment.DefaultConnection == null) + // { + // TradingEnvironment.DefaultConnection = new BittrexConnector(); + // } + // DirectoryExtensions.EnsureDirectoryExists(TradingBotEnvironment.BaseDataDirectory); + + // LockFile.Lock(); + //} + + //private void Prepare(){ + // if (!LockFile.IsLocked){ + // LockFile.Lock(); + // } + + // bool shouldSave = false; + + // if (!Directory.Exists(Path.Combine(TradingBotEnvironment.BaseDataDirectory,"sys"))){ + // Directory.CreateDirectory(Path.Combine(TradingBotEnvironment.BaseDataDirectory, "sys")); + // } + + // if (File.Exists(Path.Combine(TradingBotEnvironment.BaseDataDirectory,"sys","connector.json"))){ + // JSON connector = JSON.ReadFrom(Path.Combine(TradingBotEnvironment.BaseDataDirectory,"sys","connector.json")); + // if (connector["class"] != null){ + // Type t = Type.GetType(connector["class"].String); + // TradingConnection c = (TradingConnection)Activator.CreateInstance(t, connector["arguments"].To()); + // TradingEnvironment.DefaultConnection = c; + // } + // } else { + // TradingEnvironment.DefaultConnection = new BittrexConnector(); + // shouldSave = true; + // } + + // if (File.Exists(Path.Combine(TradingBotEnvironment.BaseDataDirectory,"sys","bots.json"))){ + // JSON bots = JSON.ReadFrom(Path.Combine(TradingBotEnvironment.BaseDataDirectory, "sys", "bots.json")); + // foreach (JSON bot in bots){ + // Type t = Type.GetType(bot["class"].String); + // TradingBot tbot = (TradingBot)Activator.CreateInstance(t, new object[] { new Guid(bot["uuid"].String) } ); + + // AddTradingBot(tbot); + // } + // } else { + // shouldSave = true; + // } + + + // if (shouldSave){ + // Save(); + // } + //} + + //public void Save() + //{ + // if (!LockFile.IsLocked){ + // throw new Exception("Cannot save, file lock not locked"); + // } + + // JSONObject connector = new JSONObject(); + // if (TradingEnvironment.DefaultConnection == null) + // { + // connector["class"] = null; + // connector["arguments"] = new JSONArray(); + // } + // else + // { + // connector["class"] = TradingEnvironment.DefaultConnection.GetType().AssemblyQualifiedName; + // connector["arguments"] = JSON.From(TradingEnvironment.DefaultConnection.getConstructorArguments()); + // } + // connector.WriteTo(Path.Combine(TradingBotEnvironment.BaseDataDirectory, "sys", "connector.json"),true); + + + // JSONArray bots = new JSONArray(); + + // foreach (TradingBot bot in TradingBots) + // { + // JSONObject o = new JSONObject(); + // o["class"] = bot.GetType().AssemblyQualifiedName; + // o["uuid"] = bot.UID.ToString(); + // bots.Add(o); + // } + // bots.WriteTo(Path.Combine(TradingBotEnvironment.BaseDataDirectory, "sys", "bots.json"),true); + + //} + + //private void Shutdown() + //{ + // if (LockFile.IsLocked){ + // LockFile.Unlock(); + // } + //} + + //public void Start(){ + + // switch (Mode){ + // case AppMode.SERVICEDAEMON: + // ServiceDaemon(); + // break; + // default: + // Run(); + // break; + // } + //} + + //public void ServiceDaemon(){ + // ServiceManager.Default.GetHashCode(); + + // while (true){ + // Thread.Sleep(1000); + + // if (File.Exists(Path.Combine(TradingEnvironment.DataDirectory, "daemon.shutdown"))){ + // File.Delete(Path.Combine(TradingEnvironment.DataDirectory, "daemon.shutdown")); + // break; + // } + // } + + // ServiceManager.Default.Shutdown(); + + //} + + //public void Run() + //{ + // foreach (TradingBot bot in tradingBots) + // { + // RunBot(bot); + // } + //} + + //public void Run(string[] uids) + //{ + // foreach (TradingBot bot in tradingBots) + // { + // if (uids.Contains(bot.UID.ToString())){ + // RunBot(bot); + // } + // } + //} + + //private void RunBot(TradingBot bot) + //{ + // Console.WriteLine("Running Bot: {0}", bot.ToString()); + + // try { + // bot.Prepare(); + // bot.Trade(); + // bot.Finish(); + // } catch (Exception e){ + // Console.WriteLine("Bot threw exception: {0}",e.ToString()); + // bot.Unlock(); + // } + //} + + + + + //public TradingBot[] TradingBots { + // get { return tradingBots.ToArray(); } + //} + + //public void AddTradingBot(TradingBot bot){ + // this.tradingBots.Add(bot); + //} + + //public void RemoveTradingBot(TradingBot bot){ + // this.tradingBots.Remove(bot); + //} + + + + + + + public Double ConvertValue(string valueSymbol,double volume,string targetSymbol){ + + if (valueSymbol.Equals(targetSymbol)){ + return volume; + } + + Market primMarket; + Market secMarket; + + try + { + primMarket = TradingEnvironment.DefaultConnection.openMarket(valueSymbol, targetSymbol); + return primMarket.getOrderBook().getVolumePrice(volume).Item2; + } catch (Exception e){ + Console.WriteLine("Direct conversion from {0} to {1} is not available",valueSymbol,targetSymbol); + } + + try + { + primMarket = TradingEnvironment.DefaultConnection.openMarket(valueSymbol, "BTC"); + secMarket = TradingEnvironment.DefaultConnection.openMarket("BTC", targetSymbol); + + return secMarket.getOrderBook().getVolumePrice(primMarket.getOrderBook().getVolumePrice(volume).Item2).Item2; + } catch (Exception e){ + Console.WriteLine("Conversion of {0} to {1} via BTC not available.",valueSymbol,targetSymbol); + } + return 0; + } + + public void DumpBalances(string targetSymbol) + { + TradingConnection c = TradingEnvironment.DefaultConnection; + double targetBalance = 0; + + foreach (trading.Balance balance in c.getBalances()) + { + if (balance.CurrentBalance > 0) + { + double targetValue = ConvertValue(balance.Currency, balance.CurrentBalance, targetSymbol); + + Console.WriteLine("Balance: {0,12:#####0.000000} {1,4} => {2,12:#####0.000000} {3}", balance.CurrentBalance, balance.Currency, targetValue, targetSymbol); + targetBalance += targetValue; + } + } + + Console.WriteLine(); + Console.WriteLine("Current {1} Value: {0,12:#####0.00} {1}", targetBalance, targetSymbol); + Console.WriteLine(); + + } + + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4394010 --- /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("TradeBot")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[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/ServiceDaemon.cs b/ServiceDaemon.cs new file mode 100644 index 0000000..e411788 --- /dev/null +++ b/ServiceDaemon.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using sharp.json.network; +using sharp.trading; +using sharp.tradebot; +using System.IO; +using System.Threading; +using sharp.json; +using sharp.tradebot.rpc; +using sharp.extensions; +using sharp.trading.bittrex; +namespace TradeBot +{ + public static class ServiceDaemon + { + public static bool daemonShouldExit = false; + public static bool ShouldExit() + { + return daemonShouldExit; + } + + public static BotManager botManager; + + public static void Run(String[] args){ + ArgumentReader ar = new ArgumentReader(args); + + while (ar.MoveNext()){ + switch (ar.Current) + { + case "--test": + TradingEnvironment.DataDirectory = "sharp.trading.data"; + TradeBotApplication.jsonPort = 33554; + break; + case "--port": + ar.MoveNext(); + TradeBotApplication.jsonPort = int.Parse(ar.Current); + return; + default: + throw new ArgumentException(String.Format("Unexpected Argument: {0}", ar.Current)); + } + } + + if (File.Exists(Path.Combine(TradingEnvironment.DataDirectory,"connector.json"))){ + JSON connector = JSON.ReadFrom(Path.Combine(TradingEnvironment.DataDirectory, "connector.json")); + if (connector["class"] != null){ + Type t = Type.GetType(connector["class"].String); + TradingConnection c = (TradingConnection)Activator.CreateInstance(t, connector["arguments"].To()); + TradingEnvironment.DefaultConnection = c; + } + } else { + TradingEnvironment.DefaultConnection = new BittrexConnector(); + } + + + + + JSONTcpServer jsonServer = new JSONTcpServer(TradeBotApplication.jsonPort); + jsonServer.ClientConnected = JSONClientConnected; + jsonServer.Start(); + + botManager = new BotManager(TradingEnvironment.DataDirectory); + botManager.LoadAllBots(); + + foreach (TradingBotInstance bot in botManager.RegisteredBots){ + bot.Prepare(); + } + + while (!ShouldExit()) + { + Thread.Sleep(100); + } + + Console.WriteLine("Servicedaemon shutting down"); + + botManager.BotEnvironment.Stop(); + + foreach (TradingBotInstance bot in botManager.RegisteredBots){ + bot.Unprepare(); + } + foreach (TradingBotInstance bot in botManager.RegisteredBots){ + bot.Unload(); + } + + botManager.Save(); + jsonServer.Stop(); + } + + private static void JSONClientConnected(JSONTcpClient client) + { + try + { + while (true) + { + JSON jrequest = client.Receive(); + RPCRequest request = jrequest.To(); + RPCResponse response = new RPCResponse(); + + if (request.Command.Equals("disconnect")) + { + break; + } + + switch (request.Command) + { + case "newbot": + Console.WriteLine("request to create new bot: {0} from {1}", request.Arguments[0], request.Arguments[1]); + response.Message = "Bot created"; + response.Success = true; + break; + case "shutdown": + response.Message = "Daemon shutting down"; + response.Success = true; + daemonShouldExit = true; + break; + + case "register": + try + { + botManager.RegisterBot(request.Arguments[0],request.Arguments[1]); + + Console.WriteLine(botManager.ToString()); + + response.Message = "registered."; + response.Success = true; + + } + catch (Exception e) + { + response.Message = String.Format("Exception: {0}", e); + response.Success = false; + } + break; + case "unregister": + try + { + botManager.UnregisterBot(Guid.Parse(request.Arguments[0])); + + response.Message = "unregistered."; + response.Success = true; + + } + catch (Exception e) + { + response.Message = String.Format("Exception: {0}", e); + response.Success = false; + } + break; + + case "load": + try + { + botManager.LoadBotAndPrepare(Guid.Parse(request.Arguments[0])); + + response.Message = "loaded."; + response.Success = true; + + } + catch (Exception e) + { + response.Message = String.Format("Exception: {0}", e); + response.Success = false; + } + break; + case "unload": + try + { + botManager.UnloadBot(Guid.Parse(request.Arguments[0])); + + response.Message = "unloaded."; + response.Success = true; + + } + catch (Exception e) + { + response.Message = String.Format("Exception: {0}", e); + response.Success = false; + } + break; + case "reload": + try + { + botManager.UnloadBot(Guid.Parse(request.Arguments[0])); + botManager.LoadBotAndPrepare(Guid.Parse(request.Arguments[0])); + + response.Message = "reloaded."; + response.Success = true; + + } + catch (Exception e) + { + response.Message = String.Format("Exception: {0}", e); + response.Success = false; + } + break; + default: + response.Success = false; + response.Message = string.Format("Unknown command: {0}", request.Command); + break; + } + client.Send(JSON.From(response)); + } + } + catch (Exception e) + { + Console.WriteLine("JSONClientConnection: Exception: " + e.ToString()); + } + client.Close(); + } + + + } +} diff --git a/TradeBot.csproj b/TradeBot.csproj new file mode 100644 index 0000000..5a081a1 --- /dev/null +++ b/TradeBot.csproj @@ -0,0 +1,71 @@ + + + + Debug + x86 + {AA4843D6-D960-4273-8CC4-3C737471D9CF} + Exe + TradeBot + TradeBot + v4.7 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + x86 + + + true + bin\Release + prompt + 4 + true + x86 + + + + + + + + + + + + + + + + + + {CAAC53CC-671C-4B1E-8403-1E53D1D40D66} + sharp.trading + + + {97CA3CA9-98B3-4492-B072-D7A5995B68E9} + sharp.extensions + + + {D9342117-3249-4D8B-87C9-51A50676B158} + sharp.json + + + {798D4516-84F8-436D-BD7F-17AD288C6776} + sharp.tradebot + + + {690293DB-4E8D-44E6-B0AD-3A4FF66E6042} + BigBot + + + + + + + \ No newline at end of file diff --git a/TradeBotHost.cs b/TradeBotHost.cs new file mode 100644 index 0000000..9ad04ae --- /dev/null +++ b/TradeBotHost.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.Remoting.Channels.Ipc; +using System.Runtime.Remoting.Channels; + +namespace TradeBot +{ + public class TradeBotHost : MarshalByRefObject + { + IpcChannel ipcChannel; + + public TradeBotHost(string hostID) + { + ipcChannel = new IpcChannel(String.Format("bot.host.{0}",hostID)); + ChannelServices.RegisterChannel(ipcChannel,true); + + + + } + } +} diff --git a/rpc/RPCRequest.cs b/rpc/RPCRequest.cs new file mode 100644 index 0000000..37a6130 --- /dev/null +++ b/rpc/RPCRequest.cs @@ -0,0 +1,9 @@ +using System; +namespace sharp.tradebot.rpc +{ + public class RPCRequest + { + public string Command; + public string[] Arguments; + } +} diff --git a/rpc/RPCResponse.cs b/rpc/RPCResponse.cs new file mode 100644 index 0000000..c1142e6 --- /dev/null +++ b/rpc/RPCResponse.cs @@ -0,0 +1,9 @@ +using System; +namespace sharp.tradebot.rpc +{ + public class RPCResponse + { + public bool Success; + public string Message; + } +}