Initial Commit
commit
1a758df642
|
@ -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
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
namespace sharp.tradebot
|
||||
{
|
||||
public class BasicBotSetup
|
||||
{
|
||||
public bool Enabled;
|
||||
|
||||
public string BaseSymbol = "";
|
||||
public string MarketSymbol = "";
|
||||
|
||||
public double ChargeBaseBalance;
|
||||
public double ChargeMarketBalance;
|
||||
}
|
||||
}
|
|
@ -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("sharp.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("")]
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
namespace sharp.tradebot
|
||||
{
|
||||
public class TradeBotBalance
|
||||
{
|
||||
public readonly string Currency;
|
||||
public double CurrentBalance;
|
||||
|
||||
public TradeBotBalance()
|
||||
{
|
||||
}
|
||||
|
||||
public TradeBotBalance(string currency)
|
||||
{
|
||||
this.Currency = currency;
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[TradeBotBalance: Currency={0,5}, CurrentBalance={1,12:#####0.00000000}]", Currency, CurrentBalance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using sharp.trading.logging;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
namespace sharp.tradebot
|
||||
{
|
||||
public class TradeBotLoader : MarshalByRefObject
|
||||
{
|
||||
public String DllPath { get; set; }
|
||||
public String ClassName { get; set; }
|
||||
public Guid UID { get; set; }
|
||||
|
||||
private AppDomain _appDomain;
|
||||
private TradingBot _instance;
|
||||
|
||||
TradingBotEnvironment environment;
|
||||
|
||||
Dictionary<Guid, pworker> pWorkers;
|
||||
|
||||
struct pworker {
|
||||
public PeriodicWorker worker;
|
||||
|
||||
public pworker(PeriodicWorker worker){
|
||||
this.worker = worker;
|
||||
}
|
||||
|
||||
public void call(){
|
||||
worker();
|
||||
}
|
||||
}
|
||||
|
||||
public TradeBotLoader()
|
||||
{
|
||||
pWorkers = new Dictionary<Guid, pworker>();
|
||||
}
|
||||
|
||||
public void RegisterPeriodic(PeriodicWorker worker, int timeout)
|
||||
{
|
||||
environment.RegisterPeriodic(worker,timeout);
|
||||
}
|
||||
public void UnregisterPeriodic(PeriodicWorker worker)
|
||||
{
|
||||
environment.UnregisterPeriodic(worker);
|
||||
}
|
||||
|
||||
/*
|
||||
public void RegisterPeriodic(PeriodicWorker worker, int timeout) {
|
||||
Guid guid = Guid.NewGuid();
|
||||
pworker pw = new pworker(worker);
|
||||
pWorkers.Add(guid, pw );
|
||||
environment.RegisterPeriodic( pWorkers[guid].call, timeout );
|
||||
}
|
||||
public void UnregisterPeriodic(PeriodicWorker worker){
|
||||
foreach (Guid guid in pWorkers.Keys){
|
||||
if (pWorkers[guid].worker == worker){
|
||||
environment.UnregisterPeriodic(pWorkers[guid].call);
|
||||
pWorkers.Remove(guid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void Load(TradingBotEnvironment environment)
|
||||
{
|
||||
this.environment = 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);
|
||||
/*
|
||||
Assembly assembly = this._appDomain.Load(File.ReadAllBytes(DllPath));
|
||||
Type type = assembly.GetType(ClassName);
|
||||
this._instance = (TradingBot)Activator.CreateInstance(type);
|
||||
*/
|
||||
this._instance = (TradingBot)this._appDomain.CreateInstanceFromAndUnwrap(DllPath, ClassName);
|
||||
this._instance.AfterLoad(environment, UID, new FileLogger(Path.Combine(environment.BaseDataDirectory, "logs", String.Format("{0}.log", UID.ToString()))),this);
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
if (this._instance != null)
|
||||
{
|
||||
lock (this._instance)
|
||||
{
|
||||
if (this._instance.IsPrepared)
|
||||
{
|
||||
this._instance.Unprepare();
|
||||
}
|
||||
this._instance.Logger.Close();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using sharp.trading;
|
||||
using System.IO;
|
||||
using sharp.json;
|
||||
using System.Linq;
|
||||
using sharp.extensions;
|
||||
using System.Diagnostics;
|
||||
using sharp.trading.services;
|
||||
using sharp.trading.logging;
|
||||
using sharp.json.attributes;
|
||||
|
||||
namespace sharp.tradebot
|
||||
{
|
||||
public abstract class TradingBot<T> : TradingBot where T:BasicBotSetup
|
||||
{
|
||||
public T BasicSetup {
|
||||
get { return this.setup.CurrentValue; }
|
||||
set { this.setup.CurrentValue = value; }
|
||||
}
|
||||
|
||||
protected override BasicBotSetup BasicBotSetup
|
||||
{
|
||||
get { return BasicSetup; }
|
||||
set { this.BasicSetup = (T)value; }
|
||||
}
|
||||
|
||||
protected FileBackedJSONValue<T> setup;
|
||||
|
||||
protected override void EnvironmentAssigned(TradingBotEnvironment env){
|
||||
this.setup = new FileBackedJSONValue<T>(Path.Combine(BaseDataPath,"botsetup.json"));
|
||||
if (this.setup.CurrentValue.IsNull()){
|
||||
this.setup.CurrentValue = Activator.CreateInstance<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
setup.Save();
|
||||
|
||||
base.Save();
|
||||
}
|
||||
}
|
||||
|
||||
[JSONClassPolicy( Policy = JSONPolicy.ATTRIBUTED)]
|
||||
public abstract class TradingBot : MarshalByRefObject
|
||||
{
|
||||
public TradingBotEnvironment TradingBotEnvironment { get; private set; }
|
||||
public TradeBotLoader TradeBotLoader { get; private set; }
|
||||
|
||||
public Guid UID { get; private set; }
|
||||
public Logger Logger { get; private set; }
|
||||
|
||||
public string BaseDataPath { get; private set; }
|
||||
|
||||
List<Order> orders = new List<Order>();
|
||||
List<TradeBotBalance> balances = new List<TradeBotBalance>();
|
||||
Market botMarket;
|
||||
|
||||
TextWriter balanceWriter;
|
||||
|
||||
protected abstract BasicBotSetup BasicBotSetup { get; set; }
|
||||
protected abstract void EnvironmentAssigned(TradingBotEnvironment env);
|
||||
|
||||
[JSONField]
|
||||
TradeBotBalance[] __balances {
|
||||
get {
|
||||
return balances.ToArray();
|
||||
}
|
||||
set
|
||||
{
|
||||
this.balances.Clear();
|
||||
if (value != null)
|
||||
{
|
||||
this.balances.AddRange(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JSONField]
|
||||
Order[] __orders
|
||||
{
|
||||
get {
|
||||
return orders.ToArray();
|
||||
}
|
||||
set
|
||||
{
|
||||
this.orders.Clear();
|
||||
if (value != null)
|
||||
{
|
||||
this.orders.AddRange(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPrepared { get; private set; }
|
||||
|
||||
public TradingBot()
|
||||
{
|
||||
}
|
||||
|
||||
public Market BotMarket {
|
||||
get
|
||||
{
|
||||
if (this.botMarket.IsNull() && !this.BasicBotSetup.BaseSymbol.Equals("") && !this.BasicBotSetup.BaseSymbol.Equals(""))
|
||||
{
|
||||
botMarket = TradingBotEnvironment.TradingConnection.openMarket(BasicBotSetup.MarketSymbol, BasicBotSetup.BaseSymbol);
|
||||
}
|
||||
return this.botMarket;
|
||||
}
|
||||
}
|
||||
|
||||
public void AfterLoad(TradingBotEnvironment environment,Guid uid,Logger logger,TradeBotLoader loader){
|
||||
this.TradingBotEnvironment = environment;
|
||||
this.UID = uid;
|
||||
this.Logger = logger;
|
||||
this.BaseDataPath = Path.Combine(environment.BaseDataDirectory, "bots", uid.ToString());
|
||||
|
||||
if (!Directory.Exists(DataDirectory)){
|
||||
Directory.CreateDirectory(DataDirectory);
|
||||
}
|
||||
|
||||
EnvironmentAssigned(environment);
|
||||
|
||||
Log("TradingBot [{0}] loaded to AppDomain [{1}]",GetType().Name,AppDomain.CurrentDomain.FriendlyName);
|
||||
}
|
||||
|
||||
public virtual void Prepare()
|
||||
{
|
||||
|
||||
//if (File.Exists(Path.Combine(DataDirectory,"orders.json"))){
|
||||
// JSON jsonorders = JSON.ReadFrom(Path.Combine(DataDirectory,"orders.json"));
|
||||
// string[] orderids = jsonorders.To<string[]>();
|
||||
// foreach (string oid in orderids){
|
||||
// this.orders.Add(TradingEnvironment.DefaultConnection.getOrder(oid));
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (File.Exists(Path.Combine(DataDirectory,"balances.json"))){
|
||||
// JSON jsonbalances = JSON.ReadFrom(Path.Combine(DataDirectory,"balances.json"));
|
||||
// this.balances.Clear();
|
||||
// this.balances.AddRange( jsonbalances.To<TradeBotBalance[]>());
|
||||
//}
|
||||
|
||||
if (File.Exists(Path.Combine(DataDirectory,"botsetup.json"))){
|
||||
JSON jbasicsetup = JSON.ReadFrom(Path.Combine(DataDirectory, "botsetup.json"));
|
||||
this.BasicBotSetup = (BasicBotSetup)JSONConverter.To(BasicBotSetup.GetType(),jbasicsetup);
|
||||
}
|
||||
|
||||
JSON jstate = JSON.ReadFrom(Path.Combine(BaseDataPath, "state.json"));
|
||||
if (jstate != null){
|
||||
JSONConverter.ApplyObject(jstate, this);
|
||||
}
|
||||
balanceWriter = new StreamWriter(new FileStream(Path.Combine(BaseDataPath, "balance.log"),FileMode.Append));
|
||||
|
||||
this.TradingBotEnvironment.RegisterPeriodic(Balancing,10);
|
||||
|
||||
IsPrepared = true;
|
||||
}
|
||||
|
||||
public virtual void Unprepare()
|
||||
{
|
||||
IsPrepared = false;
|
||||
this.TradingBotEnvironment.UnregisterPeriodic(Balancing);
|
||||
balanceWriter.Close();
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
public virtual void Save(){
|
||||
JSON.From(this).WriteTo(Path.Combine(BaseDataPath, "state.json"),true);
|
||||
}
|
||||
|
||||
public Order[] Orders {
|
||||
get { return this.orders.ToArray(); }
|
||||
}
|
||||
|
||||
public Order getOrder(string orderID){
|
||||
foreach (Order o in this.orders){
|
||||
if (o.OrderID.Equals(orderID)){
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
Order order = TradingEnvironment.DefaultConnection.getOrder(orderID);
|
||||
return order;
|
||||
}
|
||||
|
||||
public void cancelOrder(Order order){
|
||||
TradingEnvironment.DefaultConnection.cancelOrder(order);
|
||||
}
|
||||
|
||||
public void cancelOrder(string orderID)
|
||||
{
|
||||
cancelOrder(getOrder(orderID));
|
||||
}
|
||||
|
||||
public Order createLimitOrder(OrderType orderType,string marketCurrency,string baseCurrency,double quantity,double limit){
|
||||
|
||||
TradeBotBalance bBase = getBalance(baseCurrency);
|
||||
TradeBotBalance bMarket = getBalance(marketCurrency);
|
||||
|
||||
Market orderMarket = TradingEnvironment.DefaultConnection.openMarket(marketCurrency, baseCurrency);
|
||||
|
||||
if (orderMarket.MinimumTradeVolume > quantity){
|
||||
Log("Refusing to create order below minimum trading volume for market! Volume: {0:#0.000000} {1} < {2:#0.000000} {1}", quantity, marketCurrency, orderMarket.MinimumTradeVolume);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (orderType == OrderType.BUY){
|
||||
if (bBase.CurrentBalance < (limit * quantity)){
|
||||
Log("Refusing order to buy {0} @{1} with balance of {2}", quantity, limit, bBase.CurrentBalance);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (bMarket.CurrentBalance < (quantity)){
|
||||
Log("Refusing order to sell {0} @{1} with balance of {2}", quantity, limit, bMarket.CurrentBalance);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Log("createLimitOrder({0},{1},{2},{3},{4})", orderType, marketCurrency, baseCurrency, quantity, limit);
|
||||
|
||||
try
|
||||
{
|
||||
Order o = TradingEnvironment.DefaultConnection.createOrder(orderType, OrderTarget.LIMIT, marketCurrency, baseCurrency, quantity, limit);
|
||||
this.orders.Add(o);
|
||||
return o;
|
||||
|
||||
} catch (Exception e){
|
||||
Log("createLimitOrder(): threw Exception: {0}", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveOrder(Order order){
|
||||
this.orders.Remove(order);
|
||||
}
|
||||
|
||||
public VolumeRate getVolumeOnOrders(){
|
||||
VolumeRate vrate = new VolumeRate();
|
||||
|
||||
foreach (Order order in this.orders){
|
||||
if (order.OrderType == OrderType.BUY){
|
||||
vrate.Volume += order.OrderVolume;
|
||||
vrate.Price += order.LimitPrice * order.OrderVolume;
|
||||
} else {
|
||||
vrate.Volume -= order.OrderVolume;
|
||||
vrate.Price -= order.LimitPrice * order.OrderVolume;
|
||||
}
|
||||
}
|
||||
|
||||
vrate.Price /= vrate.Volume;
|
||||
|
||||
return vrate;
|
||||
}
|
||||
|
||||
/* Balances */
|
||||
|
||||
public TradeBotBalance getBalance(string symbol){
|
||||
if (symbol.IsNull() || symbol.Equals(""))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (TradeBotBalance b in balances){
|
||||
if (b.Currency.Equals(symbol)){
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
TradeBotBalance balance = new TradeBotBalance(symbol);
|
||||
balances.Add(balance);
|
||||
|
||||
return balance;
|
||||
}
|
||||
|
||||
|
||||
public T loadJSON<T>(string filename){
|
||||
if (File.Exists(Path.Combine(DataDirectory, filename)))
|
||||
{
|
||||
return JSON.ReadFrom(Path.Combine(DataDirectory, filename)).To<T>();
|
||||
}
|
||||
|
||||
if (typeof(T).IsArray){
|
||||
return (T)(object)Array.CreateInstance(typeof(T).GetElementType(), 0);
|
||||
}
|
||||
|
||||
return Activator.CreateInstance<T>();
|
||||
}
|
||||
|
||||
public void saveJSON(object o, string filename){
|
||||
JSONConverter.From(o).WriteTo(Path.Combine(DataDirectory, filename),true);
|
||||
}
|
||||
|
||||
|
||||
public string DataDirectory {
|
||||
get { return BaseDataPath; }
|
||||
}
|
||||
|
||||
public void Log(string format,params object[] args){
|
||||
Logger.Log(format,args);
|
||||
}
|
||||
|
||||
public void DumpBalances(){
|
||||
foreach (TradeBotBalance balance in balances){
|
||||
Log(balance.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual int SchedulingIntervall()
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public virtual void Balancing(){
|
||||
|
||||
if (BasicBotSetup.Enabled)
|
||||
{
|
||||
TradeBotBalance bMarket = getBalance(BasicBotSetup.MarketSymbol);
|
||||
TradeBotBalance bBase = getBalance(BasicBotSetup.BaseSymbol);
|
||||
bool charged = false;
|
||||
|
||||
if (BasicBotSetup.ChargeBaseBalance != 0){
|
||||
bBase.CurrentBalance += BasicBotSetup.ChargeBaseBalance;
|
||||
charged = true;
|
||||
}
|
||||
if (BasicBotSetup.ChargeMarketBalance != 0){
|
||||
bMarket.CurrentBalance += BasicBotSetup.ChargeMarketBalance;
|
||||
charged = true;
|
||||
}
|
||||
|
||||
if (charged){
|
||||
Log("Charged balances: {0,11:####0.00000000} {1} / {2,11:####0.00000000} {3}", BasicBotSetup.ChargeBaseBalance, BasicBotSetup.BaseSymbol, BasicBotSetup.ChargeMarketBalance, BasicBotSetup.MarketSymbol);
|
||||
balanceWriter.WriteLine("{0}\t{1}\t{2}\t{3,12:0.00000000}\t{4,12:0.00000000}\t{5,12:0.00000000}\t{6,12:0.00000000}\t{7,12:0.00000000}", DateTime.Now, "-", "CHARGE", BasicBotSetup.ChargeMarketBalance,BasicBotSetup.ChargeBaseBalance,0,bBase.CurrentBalance,bMarket.CurrentBalance);
|
||||
balanceWriter.Flush();
|
||||
|
||||
BasicBotSetup.ChargeMarketBalance = 0;
|
||||
BasicBotSetup.ChargeBaseBalance = 0;
|
||||
}
|
||||
|
||||
foreach (Order order in this.__orders)
|
||||
{
|
||||
TradingBotEnvironment.TradingConnection.refreshOrder(order);
|
||||
if (!order.IsOpen)
|
||||
{
|
||||
bBase.CurrentBalance -= order.PayedFees;
|
||||
if (order.OrderType == OrderType.BUY){
|
||||
bBase.CurrentBalance -= order.PayedPrice;
|
||||
bMarket.CurrentBalance += order.FilledVolume;
|
||||
} else {
|
||||
bBase.CurrentBalance += order.PayedPrice;
|
||||
bMarket.CurrentBalance -= order.FilledVolume;
|
||||
}
|
||||
this.RemoveOrder(order);
|
||||
|
||||
Log("Order has been closed: {5} {0,11:####0.00000000} {1} / {2,11:####0.00000000} {3} [ FEE: {4,11:####0.00000000} {3} ]",
|
||||
order.FilledVolume,
|
||||
BasicBotSetup.MarketSymbol,
|
||||
order.PayedPrice,
|
||||
BasicBotSetup.BaseSymbol,
|
||||
order.PayedFees,
|
||||
order.OrderType
|
||||
);
|
||||
|
||||
balanceWriter.WriteLine("{0}\t{1}\t{2}\t{3:#0.00000000}\t{4:#0.00000000}\t{5:#0.00000000}\t{6:#0.00000000}\t{7:#0.00000000}", DateTime.Now, order.OrderID, order.OrderType, order.FilledVolume,order.PayedPrice,order.PayedFees,bBase.CurrentBalance,bMarket.CurrentBalance);
|
||||
balanceWriter.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
using sharp.trading;
|
||||
using System.IO;
|
||||
using System.Timers;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace sharp.tradebot
|
||||
{
|
||||
public delegate void PeriodicWorker();
|
||||
|
||||
public class TradingBotEnvironment : MarshalByRefObject
|
||||
{
|
||||
public string BaseDataDirectory { get; private set; }
|
||||
public TradingConnection TradingConnection { get; private set; }
|
||||
|
||||
Thread periodicsThread;
|
||||
bool contPeriodics = true;
|
||||
|
||||
List<PeriodicTask> periodicTasks = new List<PeriodicTask>();
|
||||
|
||||
|
||||
public TradingBotEnvironment(TradingConnection connection,string baseDataDirectory){
|
||||
BaseDataDirectory = baseDataDirectory;
|
||||
TradingConnection = connection;
|
||||
periodicsThread = new Thread(periodics);
|
||||
periodicsThread.Start();
|
||||
}
|
||||
|
||||
public void RegisterPeriodic(PeriodicWorker worker,int timeout){
|
||||
lock (periodicTasks){
|
||||
periodicTasks.Add(new PeriodicTask(timeout,worker));
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterPeriodic(PeriodicWorker worker)
|
||||
{
|
||||
lock (periodicTasks)
|
||||
{
|
||||
foreach (PeriodicTask ptask in periodicTasks.ToArray()){
|
||||
if (ptask.worker == worker){
|
||||
periodicTasks.Remove(ptask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop(){
|
||||
lock (this){
|
||||
this.contPeriodics = false;
|
||||
}
|
||||
this.periodicsThread.Join();
|
||||
}
|
||||
|
||||
private void periodics(){
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
while (true){
|
||||
|
||||
lock (this){
|
||||
if (!contPeriodics)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lock (periodicTasks){
|
||||
foreach (PeriodicTask ptask in periodicTasks){
|
||||
ptask.Check();
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
}
|
||||
|
||||
class PeriodicTask {
|
||||
public DateTime lastRun;
|
||||
public Int64 interval;
|
||||
public PeriodicWorker worker;
|
||||
|
||||
public PeriodicTask(Int64 interval,PeriodicWorker worker){
|
||||
this.worker = worker;
|
||||
this.interval = interval;
|
||||
this.lastRun = DateTime.Now;
|
||||
}
|
||||
|
||||
public void Check()
|
||||
{
|
||||
if ((this.lastRun == null) || ((DateTime.Now - this.lastRun).TotalSeconds >= this.interval))
|
||||
{
|
||||
this.lastRun = DateTime.Now;
|
||||
try
|
||||
{
|
||||
lock (this.worker.Target){
|
||||
if (!typeof(TradingBot).IsInstanceOfType(this.worker.Target) || ((TradingBot)this.worker.Target).IsPrepared){
|
||||
try {
|
||||
this.worker();
|
||||
} catch (Exception e){
|
||||
Console.WriteLine("Exception: {0}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
Console.WriteLine("Exception: {0}",e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
namespace sharp.trading.logging
|
||||
{
|
||||
public class FileLogger : Logger
|
||||
{
|
||||
TextWriter writer;
|
||||
|
||||
public FileLogger(string filename)
|
||||
{
|
||||
this.writer = new StreamWriter(new FileStream(filename, FileMode.Append));
|
||||
}
|
||||
|
||||
protected override void log(string line)
|
||||
{
|
||||
this.writer.WriteLine(line);
|
||||
this.writer.Flush();
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
this.writer.Close();
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace sharp.trading.logging
|
||||
{
|
||||
public abstract class Logger : MarshalByRefObject
|
||||
{
|
||||
|
||||
protected abstract void log(string line);
|
||||
|
||||
public void Log(string format, params object[] args)
|
||||
{
|
||||
string preformat = string.Format(format, args);
|
||||
string postformat = string.Format("{0} {1} {2}", DateTime.Now.ToLocalTime(), Process.GetCurrentProcess().Id, preformat);
|
||||
lock (this)
|
||||
{
|
||||
log(postformat);
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(Exception e){
|
||||
Log("An Exception occured: {0} in {1}", e.ToString(),e.StackTrace);
|
||||
}
|
||||
|
||||
public virtual void Close(){
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?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>{798D4516-84F8-436D-BD7F-17AD288C6776}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>sharp.tradebot</RootNamespace>
|
||||
<AssemblyName>sharp.tradebot</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TradingBot.cs" />
|
||||
<Compile Include="TradingBotEnvironment.cs" />
|
||||
<Compile Include="TradeBotBalance.cs" />
|
||||
<Compile Include="logging\FileLogger.cs" />
|
||||
<Compile Include="logging\Logger.cs" />
|
||||
<Compile Include="TradeBotLoader.cs" />
|
||||
<Compile Include="BasicBotSetup.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\sharp-trading\sharp.trading.csproj">
|
||||
<Project>{CAAC53CC-671C-4B1E-8403-1E53D1D40D66}</Project>
|
||||
<Name>sharp.trading</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\sharp-json\sharp.json.csproj">
|
||||
<Project>{D9342117-3249-4D8B-87C9-51A50676B158}</Project>
|
||||
<Name>sharp.json</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\sharp-extensions\sharp.extensions.csproj">
|
||||
<Project>{97CA3CA9-98B3-4492-B072-D7A5995B68E9}</Project>
|
||||
<Name>sharp.extensions</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="logging\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
Loading…
Reference in New Issue