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