master
Harald Wolff 2017-11-23 13:08:10 +01:00
commit 7c28bbbc60
12 changed files with 1771 additions and 0 deletions

40
.gitignore vendored 100644
View File

@ -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

255
BigBot.cs 100644
View File

@ -0,0 +1,255 @@
using System;
using sharp.tradebot;
using sharp.json;
using sharp.trading;
using System.IO;
using sharp.extensions;
using sharp.json.attributes;
using System.Globalization;
namespace BigBot
{
[JSONClassPolicy( Policy = JSONPolicy.ATTRIBUTED)]
public class BigBot : TradingBot<BigBotSetup>
{
FileBackedJSONValue<BigBotSetup> Setup;
public BigBot()
{
}
sharp.tradebot.TradeBotBalance balanceBase;
sharp.tradebot.TradeBotBalance balanceMarket;
[JSONField]
public double CurrentMarketCosts;
[JSONField]
double lastCenterRate;
[JSONField]
double lastDT;
[JSONField]
public SmoothValue[] Gliders;
[JSONField]
public SmoothValue[] dT;
[JSONField]
public SmoothValue[] dTdT;
[JSONField]
public string currentOrderID;
public override void Prepare()
{
base.Prepare();
Setup = new FileBackedJSONValue<BigBotSetup>(Path.Combine(BaseDataPath, "setup.json"));
if (Setup.CurrentValue == null){
Setup.CurrentValue = new BigBotSetup();
Setup.Save();
}
if (this.dT.IsNull())
{
initialize_dT();
}
if (this.dTdT.IsNull())
{
initialize_dTdT();
}
TradingBotEnvironment.RegisterPeriodic(Worker,15);
Log("Prepared");
}
public override void Save(){
Setup.Save();
base.Save();
}
public override void Unprepare()
{
TradingBotEnvironment.UnregisterPeriodic(Worker);
Save();
Log("Unprepared");
base.Unprepare();
}
private bool Check(){
balanceBase = getBalance(Setup.CurrentValue.BaseSymbol);
balanceMarket = getBalance(Setup.CurrentValue.MarketSymbol);
if (balanceBase.IsNull() || balanceMarket.IsNull()){
Log("check failed: balances not available");
return false;
}
return true;
}
private void CheckCurrentOrder(){
if (!currentOrderID.IsNull()){
Order order = getOrder(currentOrderID);
if (!order.IsNull() && !order.IsOpen){
balanceBase.CurrentBalance -= order.PayedFees;
CurrentMarketCosts += order.PayedFees;
if (order.OrderType == OrderType.BUY){
CurrentMarketCosts += order.PayedPrice;
balanceBase.CurrentBalance -= order.PayedPrice;
balanceMarket.CurrentBalance += order.FilledVolume;
} else {
CurrentMarketCosts -= order.PayedPrice;
balanceBase.CurrentBalance += order.PayedPrice;
balanceMarket.CurrentBalance -= order.FilledVolume;
}
}
}
}
private void Worker()
{
if (Setup.CurrentValue.Enabled && Check())
{
Log("BigBot: Worker() called and enabled!");
Log("Next run...");
Market market = TradingBotEnvironment.TradingConnection.openMarket(Setup.CurrentValue.MarketSymbol, Setup.CurrentValue.BaseSymbol);
OrderBook orderBook = market.getOrderBook();
orderBook.Refresh();
System.Tuple<double, double> currentCheck = orderBook.getVolumePrice(Setup.CurrentValue.MarketCheckVolume);
double centerPrice = (currentCheck.Item1 + currentCheck.Item2) / 2;
double centerRate = centerPrice / Setup.CurrentValue.MarketCheckVolume;
if (this.Gliders.IsNull())
{
initializeGliders(centerRate);
}
else
{
foreach (SmoothValue glide in this.Gliders)
{
glide.Add(centerRate);
}
}
double _dT = (((centerRate - lastCenterRate) / centerRate)) * 100.0;
double _dTdT = (_dT - lastDT);
foreach (SmoothValue dt in this.dT)
{
dt.Add(_dT);
}
foreach (SmoothValue dtdt in this.dTdT)
{
dtdt.Add(_dTdT);
}
double[] Indicators = new double[Gliders.Length - 1];
for (int n = 0; n < Indicators.Length; n++)
{
Indicators[n] = 1.0 - (this.Gliders[0].CurrentValue / this.Gliders[n + 1].CurrentValue);
}
lastCenterRate = centerRate;
lastDT = _dT;
Log("Current volumized Market Values: Ask: {0,11:####0.00000000} {2} Bid: {1,11:####0.00000000} {2}", currentCheck.Item1, currentCheck.Item2, Setup.CurrentValue.BaseSymbol);
Log("Current volumized Market Spread: {0,6:##0.00}%", ((currentCheck.Item1 / currentCheck.Item2)-1) * 100);
Log("Current volumized Center Rate: {0,11:####0.00000000} {1}", centerRate, Setup.CurrentValue.BaseSymbol);
Log("Current indicators [ 0..3 ]: {0,6:##0.00}% / {1,6:##0.00}% / {2,6:##0.00}% / {3,6:##0.00}%", Indicators[0] * 100,Indicators[1] * 100,Indicators[2] * 100,Indicators[3] * 100);
WriteHistory();
Save();
market.Close();
}
}
private void initializeGliders(double center)
{
double k = 1;
this.Gliders = new SmoothValue[10];
for (int n = 0; n < this.Gliders.Length; n++)
{
this.Gliders[n] = new SmoothValue(k);
this.Gliders[n].Set(center);
k /= 10;
}
}
private void initialize_dT()
{
double k = 1;
this.dT = new SmoothValue[8];
for (int n = 0; n < this.dT.Length; n++)
{
this.dT[n] = new SmoothValue(k);
k /= 2;
}
}
private void initialize_dTdT()
{
double k = 1;
this.dTdT = new SmoothValue[8];
for (int n = 0; n < this.dTdT.Length; n++)
{
this.dTdT[n] = new SmoothValue(k);
k /= 2;
}
}
public void WriteHistory()
{
FileStream s = new FileStream(Path.Combine(BaseDataPath, "gliders.csv"), FileMode.Append);
StreamWriter w = new StreamWriter(s);
foreach (SmoothValue glide in this.Gliders)
{
w.Write(glide.CurrentValue.ToString(CultureInfo.InvariantCulture));
w.Write('\t');
}
w.WriteLine();
w.Close();
s = new FileStream(Path.Combine(BaseDataPath, "dt.csv"), FileMode.Append);
w = new StreamWriter(s);
foreach (SmoothValue dt in this.dT)
{
w.Write(dt.CurrentValue.ToString(CultureInfo.InvariantCulture));
w.Write('\t');
}
w.WriteLine();
w.Close();
s = new FileStream(Path.Combine(BaseDataPath, "dtdt.csv"), FileMode.Append);
w = new StreamWriter(s);
foreach (SmoothValue dtdt in this.dTdT)
{
w.Write(dtdt.CurrentValue.ToString(CultureInfo.InvariantCulture));
w.Write('\t');
}
w.WriteLine();
w.Close();
}
}
public class BigBotSetup : BasicBotSetup
{
public double MarketCheckVolume = 1;
}
}

63
BigBot.csproj 100644
View File

@ -0,0 +1,63 @@
<?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>{690293DB-4E8D-44E6-B0AD-3A4FF66E6042}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>BigBot</RootNamespace>
<AssemblyName>BigBot</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="BigBot.cs" />
<Compile Include="SmoothValue.cs" />
<Compile Include="MarketValueBot.cs" />
<Compile Include="DifferentingBot.cs" />
<Compile Include="HistoryBot.cs" />
<Compile Include="SimpleBot.cs" />
<Compile Include="SpreadBot.cs" />
<Compile Include="StatisticalBot.cs" />
<Compile Include="TargetValueBot.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\sharp.tradebot\sharp.tradebot.csproj">
<Project>{798D4516-84F8-436D-BD7F-17AD288C6776}</Project>
<Name>sharp.tradebot</Name>
</ProjectReference>
<ProjectReference Include="..\sharp-trading\sharp.trading.csproj">
<Project>{CAAC53CC-671C-4B1E-8403-1E53D1D40D66}</Project>
<Name>sharp.trading</Name>
</ProjectReference>
<ProjectReference Include="..\sharp-extensions\sharp.extensions.csproj">
<Project>{97CA3CA9-98B3-4492-B072-D7A5995B68E9}</Project>
<Name>sharp.extensions</Name>
</ProjectReference>
<ProjectReference Include="..\sharp-json\sharp.json.csproj">
<Project>{D9342117-3249-4D8B-87C9-51A50676B158}</Project>
<Name>sharp.json</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

444
DifferentingBot.cs 100644
View File

@ -0,0 +1,444 @@
using System;
using sharp.tradebot;
using sharp.json.attributes;
using sharp.extensions;
using sharp.trading;
using System.IO;
using System.Globalization;
namespace BigBot
{
public class DifferentingBot : TradingBot<DifferentialSetup>
{
[JSONField]
GlidingHistory currentValue = new GlidingHistory(1);
[JSONField]
GlidingHistory[] GlidingHistories;
[JSONField]
double targetVolume = 1;
[JSONField]
string currentOrderID;
[JSONField]
VolumeRate currentVolumeRate;
[JSONField]
double lastOrderLimit;
[JSONField]
SimpleHighLowDetector detector = new SimpleHighLowDetector();
TextWriter historyWriter;
public override void Prepare()
{
base.Prepare();
double k = 0.25;
if (this.GlidingHistories.IsNull())
{
k = 0.25;
this.GlidingHistories = new GlidingHistory[4];
for (int n = 0; n < this.GlidingHistories.Length;n++){
this.GlidingHistories[n] = new GlidingHistory(k);
k /= 2;
}
}
if (lastOrderLimit == 0){
lastOrderLimit = currentVolumeRate.UnityPrice;
}
historyWriter = new StreamWriter(new FileStream(Path.Combine(BaseDataPath, "history.csv"), FileMode.Append));
TradingBotEnvironment.RegisterPeriodic(Trade,60);
}
public override void Unprepare()
{
TradingBotEnvironment.UnregisterPeriodic(Trade);
historyWriter.Close();
base.Unprepare();
}
private void Trade(){
if (BasicSetup.Enabled){
TradeBotBalance bMarket = getBalance(BasicSetup.MarketSymbol);
OrderBook orderBook = BotMarket.getOrderBook();
System.Tuple<double,double> marketCheck = orderBook.getVolumePrice(BasicSetup.MarketCheckVolume);
double currentAskRate = marketCheck.Item1 / BasicSetup.MarketCheckVolume;
double currentBidRate = marketCheck.Item2 / BasicSetup.MarketCheckVolume;
double currentCenterRate = (currentAskRate + currentBidRate) / 2;
currentValue.Add(currentCenterRate);
foreach (GlidingHistory gh in this.GlidingHistories)
{
gh.Add(currentCenterRate);
}
//detector.Add(this.GlidingHistories[0].centerRate);
detector.Add(currentCenterRate);
writeHistory(currentCenterRate);
/* Indicators... */
double qEMA = (this.GlidingHistories[2].centerRate - currentCenterRate) / this.GlidingHistories[2].centerRate;
double currentDTDT0 = this.GlidingHistories[0].dTdT;
/* if (
((qEMA > 0) && (targetVolume < 1.0 )) ||
((qEMA < 0) && (targetVolume > 1.0 ))
){
targetVolume = 1;
}
*/
/*
if (!BasicSetup.ResetTargetVolume)
{
targetVolume *= (1.0 + qEMA);
} else {
targetVolume = 1.0;
BasicSetup.ResetTargetVolume = false;
}
if (currentCenterRate > this.currentVolumeRate.UnityPrice){
targetVolume = 0.85;
} else {
targetVolume = 1.15;
}
double currentOrderVolume = (bMarket.CurrentBalance * targetVolume) - bMarket.CurrentBalance;
if ((Math.Abs(currentOrderVolume) < BotMarket.MinimumTradeVolume) && (BasicSetup.IncreaseOrderVolumeToMinimum)){
currentOrderVolume *= BotMarket.MinimumTradeVolume / Math.Abs(currentOrderVolume);
}
*/
double currentOrderVolume = currentVolumeRate.Volume * BasicSetup.RelativeTradeVolume;
if (currentOrderVolume < BotMarket.MinimumTradeVolume)
{
currentOrderVolume = BotMarket.MinimumTradeVolume;
}
double diffDT01 = this.GlidingHistories[0].dT - this.GlidingHistories[1].dT;
System.Tuple<double, double> currentOrderPrices = orderBook.getVolumePrice(Math.Abs(currentOrderVolume));
double currentBuyRate = currentOrderPrices.Item1 / Math.Abs(currentOrderVolume);
double currentSellRate = currentOrderPrices.Item2 / Math.Abs(currentOrderVolume);
double currentBuyMargin = lastOrderLimit * (1.0 - BasicSetup.MarginBuy);
double currentSellMargin = lastOrderLimit * (1.0 + BasicSetup.MarginSell);
Log("Current: {0,11:###0.000000} {1,4} EMA: {2,11:###0.000000} {1}", currentCenterRate, BasicSetup.BaseSymbol, this.GlidingHistories[2].centerRate.CurrentValue);
Log("qEMA: {0,8:###0.0000} % Target Volume: {1,11:###0.000000}", qEMA * 100, targetVolume);
Log("Current Market Balance: {0,11:###0.000000} {3,4} / {1,11:###0.000000} {4,4} = {2,11:###0.000000} {3,4}/{4,4}",
currentVolumeRate.Price,
currentVolumeRate.Volume,
currentVolumeRate.UnityPrice,
BasicSetup.BaseSymbol,
BasicSetup.MarketSymbol);
Log("Current dT(0) - dT(1): {0,8:###0.0000} % / min Current dT(center): {1,8:###0.0000} %", diffDT01, currentValue.dT.CurrentValue);
Log("Current Order Volume: {0,11:###0.000000} {2,4} ( Minimum Order Volume: {1,11:###0.000000} {2,4} )", currentOrderVolume, BotMarket.MinimumTradeVolume, BasicSetup.MarketSymbol);
Log("Current Order Volume rates: {0,11:###0.000000} {2,4} [ BUY ] / {1,11:###0.000000} {2,4} [ SELL ]",currentBuyRate,currentSellRate,BasicSetup.BaseSymbol);
Log("Current Order Margins: {0,11:###0.000000} {2,4} [ BUY ] / {1,11:###0.000000} {2,4} [ SELL ]", currentBuyMargin, currentSellMargin, BasicSetup.BaseSymbol);
Log("{0}", this.detector.ToString());
if (BasicSetup.OrderFixedVolume != 0){
if (!currentOrderID.IsNull()){
cancelOrder(currentOrderID);
} else {
double orderVolume = Math.Abs(BasicSetup.OrderFixedVolume);
OrderType orderType = BasicSetup.OrderFixedVolume > 0 ? OrderType.BUY : OrderType.SELL;
double orderLimit = orderType == OrderType.BUY ? orderBook.CurrentAsk : orderBook.CurrentBid;
if (orderVolume >= BotMarket.MinimumTradeVolume)
{
Log("Creating fixed volume Order: {2,4} {0,11:###0.000000} {1,4}", orderVolume, BasicSetup.MarketSymbol, orderType);
Order o = createLimitOrder(orderType, BasicSetup.MarketSymbol, BasicSetup.BaseSymbol, orderVolume, orderLimit);
if (o != null){
currentOrderID = o.OrderID;
}
BasicSetup.OrderFixedVolume = 0;
Save();
}
else
{
Log("Fixed volume too low for minimum Trade Size of {0,11:###0.000000} {1,4}", BotMarket.MinimumTradeVolume, BasicSetup.MarketSymbol);
}
}
} else {
if (!currentOrderID.IsNull())
{
cancelOrder(currentOrderID);
/* } else if (
(this.GlidingHistories[2].dT.LastValue > 0) &&
(this.GlidingHistories[2].dT.CurrentValue <= 0) &&
(this.GlidingHistories[0].centerRate.CurrentValue < this.GlidingHistories[2].centerRate.CurrentValue) &&
(currentSellRate >= currentSellMargin)
)
{*/
} else if (this.detector.HighDetected && (currentSellRate >= currentSellMargin))
{
// Sell Signal
Order o = createLimitOrder(OrderType.SELL, BasicSetup.MarketSymbol, BasicSetup.BaseSymbol, currentOrderVolume, currentSellRate);
if (o != null)
{
currentOrderID = o.OrderID;
lastOrderLimit = currentSellRate;
}
/* } else if (
(this.GlidingHistories[2].dT.LastValue < 0) &&
(this.GlidingHistories[2].dT.CurrentValue >= 0) &&
(this.GlidingHistories[0].centerRate.CurrentValue >= this.GlidingHistories[2].centerRate.CurrentValue) &&
(currentBuyRate <= currentBuyMargin)
)*/
} else if (this.detector.LowDetected && (currentBuyRate <= currentBuyMargin))
{
// Buy Signal
Order o = createLimitOrder(OrderType.BUY, BasicSetup.MarketSymbol, BasicSetup.BaseSymbol, currentOrderVolume, currentBuyRate);
if (o != null)
{
currentOrderID = o.OrderID;
lastOrderLimit = currentBuyRate;
}
}
/*
double orderVolume = Math.Abs(currentOrderVolume);
OrderType orderType = currentOrderVolume < 0 ? OrderType.SELL : OrderType.BUY;
if (orderVolume >= BotMarket.MinimumTradeVolume)
{
double margin = (orderType == OrderType.BUY) ? BasicSetup.MarginBuy : BasicSetup.MarginSell;
double orderMargin = (orderType == OrderType.BUY) ? (currentVolumeRate.UnityPrice / currentBuyRate) - 1.0 : (currentSellRate / currentVolumeRate.UnityPrice) - 1.0;
double orderLimit = (orderType == OrderType.BUY) ? currentBuyRate : currentSellRate;
if (orderMargin > margin){
Log("Order Margin reached");
if (currentOrderID.IsNull())
{
if (
((orderType == OrderType.BUY) && (diffDT01 >= 0) && (this.currentValue.dT.CurrentValue > -0.0025)) ||
((orderType == OrderType.SELL) && (diffDT01 <= 0) && (this.currentValue.dT.CurrentValue < 0.0025))
)
{
Order order = createLimitOrder(orderType, BasicSetup.MarketSymbol, BasicSetup.BaseSymbol, orderVolume, orderLimit);
if (!order.IsNull()){
currentOrderID = order.OrderID;
targetVolume = 1.0;
}
}
else
{
Log("waiting for dt...");
}
}
else
{
cancelOrder(currentOrderID);
}
}
}
*/
}
DumpBalances();
}
}
public override void Balancing()
{
if (!this.currentOrderID.IsNull()){
Order currentOrder = getOrder(currentOrderID);
if (!currentOrder.IsOpen)
{
if (currentOrder.OrderType == OrderType.BUY){
this.currentVolumeRate.Volume += currentOrder.FilledVolume;
this.currentVolumeRate.Price += currentOrder.PayedPrice + currentOrder.PayedFees;
} else {
this.currentVolumeRate.Volume -= currentOrder.FilledVolume;
this.currentVolumeRate.Price -= currentOrder.PayedPrice - currentOrder.PayedFees;
}
currentOrderID = null;
}
}
base.Balancing();
}
private void writeHistory(double currentCenterRate){
historyWriter.Write("{0}\t{1}",DateTime.Now.ToString(),currentCenterRate.ToString(CultureInfo.InvariantCulture));
/* for (int n = 0; n < this.GlidingCenterRates.Length;n++){
historyWriter.Write("\t{0}\t{1}\t{2}",
GlidingCenterRates[n].CurrentValue.ToString(CultureInfo.InvariantCulture),
this.dT[n].ToString(CultureInfo.InvariantCulture),
this.dTdT[n].ToString(CultureInfo.InvariantCulture)
);
}
*/
foreach (GlidingHistory gh in this.GlidingHistories)
{
historyWriter.Write("\t{0}\t{1}\t{2}",
gh.centerRate.CurrentValue.ToString(CultureInfo.InvariantCulture),
gh.dT.CurrentValue.ToString(CultureInfo.InvariantCulture),
gh.dTdT.CurrentValue.ToString(CultureInfo.InvariantCulture)
);
}
historyWriter.Write("\t{0}\t{1}\t{2}",
currentValue.centerRate.CurrentValue.ToString(CultureInfo.InvariantCulture),
currentValue.dT.CurrentValue.ToString(CultureInfo.InvariantCulture),
currentValue.dTdT.CurrentValue.ToString(CultureInfo.InvariantCulture)
);
historyWriter.Write("\t{0}", targetVolume.ToString(CultureInfo.InvariantCulture));
historyWriter.WriteLine();
historyWriter.Flush();
}
public enum RiseFall { NONE, DETECT, RISING, FALLING };
private class SimpleHighLowDetector
{
public RiseFall Currently { get; private set; } = RiseFall.NONE;
public double Margin { get; set; } = 0.005;
public double CurrentExtremum { get; private set; }
public bool LowDetected { get; private set; }
public bool HighDetected { get; private set; }
public double LastLow { get; private set; }
public double LastHigh { get; private set; }
public void Add(double value){
LowDetected = false;
HighDetected = false;
if (Currently == RiseFall.NONE)
{
CurrentExtremum = value;
Currently = RiseFall.DETECT;
} else if (Currently == RiseFall.DETECT)
{
if (value > (CurrentExtremum * (1 + Margin))){
Currently = RiseFall.RISING;
CurrentExtremum = value;
} else if (value < (CurrentExtremum * ( 1 - Margin))){
Currently = RiseFall.FALLING;
CurrentExtremum = value;
}
} else {
if (Currently == RiseFall.FALLING)
{
if (value < CurrentExtremum){
CurrentExtremum = value;
} else if (value > ((1.0 + Margin) * CurrentExtremum)){
Currently = RiseFall.RISING;
LowDetected = true;
LastLow = CurrentExtremum;
}
} else if (Currently == RiseFall.RISING)
{
if (value > CurrentExtremum){
CurrentExtremum = value;
} else if (value < ((1.0 - Margin) * CurrentExtremum)){
Currently = RiseFall.FALLING;
HighDetected = true;
LastHigh = CurrentExtremum;
}
}
}
}
public override string ToString()
{
return string.Format("[SimpleHighLowDetector: Currently={0}, Margin={1}, CurrentExtremum={2}, LowDetected={3}, HighDetected={4}]", Currently, Margin, CurrentExtremum, LowDetected, HighDetected);
}
}
private class GlidingHistory {
public SmoothValue centerRate;
public SmoothValue dT;
public SmoothValue dTdT;
public GlidingHistory()
: this(0.25)
{
}
public GlidingHistory(double k){
this.centerRate = new SmoothValue(k);
this.dT = new SmoothValue(k);
this.dTdT = new SmoothValue(k);
}
public Double Kp {
get { return this.centerRate.Kp; }
set {
this.centerRate.Kp = value;
this.dT.Kp = value;
this.dTdT.Kp = value;
}
}
public void Add(double centerRateValue){
if (centerRate.CurrentValue == 0){
this.centerRate.Set(centerRateValue);
}
this.centerRate.Add(centerRateValue);
this.dT.Add(this.centerRate.dT);
this.dTdT.Add(this.dT.dT);
}
}
}
public class DifferentialSetup : BasicBotSetup
{
public double MarketCheckVolume = 1;
public double OrderFixedVolume;
public bool IncreaseOrderVolumeToMinimum;
public bool ResetTargetVolume;
public double MarginBuy = 0.02;
public double MarginSell = 0.02;
public double RelativeTradeVolume = 0.2;
}
}

206
HistoryBot.cs 100644
View File

@ -0,0 +1,206 @@
using System;
using sharp.json;
using System.IO;
using sharp.trading;
using sharp.trading.cache;
using sharp.extensions;
namespace sharp.tradebot
{
public class HistoryBot : TradingBot<BasicBotSetup>
{
public FileBackedJSONValue<SetupClass> Setup;
public FileBackedJSONValue<string> CurrentOrderID;
public HistoryBot()
{
initialize();
}
private void initialize()
{
Setup = new FileBackedJSONValue<SetupClass>(Path.Combine(DataDirectory, "setup.json"));
CurrentOrderID = new FileBackedJSONValue<string>(Path.Combine(DataDirectory, "currentorder.json"));
}
public override void Prepare()
{
base.Prepare();
if (Setup.CurrentValue == null){
Setup.CurrentValue = new SetupClass();
}
}
public void Trade()
{
TradeBotBalance balanceBase = getBalance(Setup.CurrentValue.BaseSymbol);
TradeBotBalance balanceMarket = getBalance(Setup.CurrentValue.MarketSymbol);
if (CurrentOrderID.CurrentValue != null){
Order o = getOrder(CurrentOrderID.CurrentValue);
if (!o.IsOpen){
if (o.OrderType == OrderType.BUY){
balanceBase.CurrentBalance -= o.PayedFees + o.PayedPrice;
balanceMarket.CurrentBalance += o.FilledVolume;
} else {
balanceBase.CurrentBalance += o.PayedPrice - o.PayedFees;
balanceMarket.CurrentBalance -= o.FilledVolume;
}
CurrentOrderID.CurrentValue = null;
Save();
}
}
if (Setup.CurrentValue.Enabled){
Log("Bot enabled");
/* Manage Balances */
if (Setup.CurrentValue.BaseBalanceChange != 0)
{
balanceBase.CurrentBalance += Setup.CurrentValue.BaseBalanceChange;
Setup.CurrentValue.BaseBalanceChange = 0;
Setup.Save();
}
if (Setup.CurrentValue.MarketBalanceChange != 0)
{
balanceMarket.CurrentBalance += Setup.CurrentValue.MarketBalanceChange;
Setup.CurrentValue.MarketBalanceChange = 0;
Setup.Save();
}
Market market = TradingEnvironment.DefaultConnection.openMarket(Setup.CurrentValue.MarketSymbol, Setup.CurrentValue.BaseSymbol);
HistoryCache cache = HistoryCache.getCache(market);
double indication = 0;
WeightedIndicator[] indicators = Setup.CurrentValue.Indicators;
foreach (WeightedIndicator wi in indicators){
double ind = cache.calulateWeightedAveragesPerVolume(wi.Volume).AveragePrice;
double weight = wi.Weight;
Log("Indicator for Volume {0,10} = {1,11:####0.00000000} with a weight of {2,7:#0.####}",wi.Volume,ind,weight);
indication += ind * wi.Weight;
}
Log("Indicator Sum: {0,11:####0.00000000}", indication);
OrderBook orderBook = market.getOrderBook();
System.Tuple<double,double> bidask = orderBook.getVolumePrice(5.0);
Log("Current Small-Volumes: {0} / {1}",bidask.Item1,bidask.Item2);
double smallbid = bidask.Item2 / 5;
double smallask = bidask.Item1 / 5;
Log("Current Small Ask: {0} Bid: {1}", smallask, smallbid);
double smallsum = (smallbid + smallask) / 2;
Log("Current Small-Indicator: {0}", smallsum);
double final = indication / (smallsum + indication);
Log("Current Final Indication: {0}", final);
double marketBalanceAsBase = orderBook.getVolumePrice(balanceMarket.CurrentBalance).Item2;
double balancesum = (balanceBase.CurrentBalance + marketBalanceAsBase);
double currentRatio = marketBalanceAsBase / balancesum;
Log("Current Balance Values: {0,11:####0.00000000} {1} / {2,11:####0.00000000} {1} = {3:#0.0000}", balanceBase.CurrentBalance, balanceBase.Currency, marketBalanceAsBase, currentRatio);
Log("Current Balance Sum: {0,11:####0.00000000} {1}", balancesum, balanceBase.Currency);
double targetMarket = balancesum / (1 + final);
double targetBase = balancesum - targetMarket;
Log("Target Balance Values: {0,11:####0.00000000} {2} / {1,11:####0.00000000} {2}", targetBase, targetMarket, balanceBase.Currency);
double diff = currentRatio - final;
diff = Math.Abs(diff);
Log("Current Indicator Diff: {0}", diff);
if (diff > Setup.CurrentValue.DiffMargin){
if (CurrentOrderID.CurrentValue != null)
{
Log("Canceling old Order before creating new one.");
TradingEnvironment.DefaultConnection.cancelOrder(CurrentOrderID.CurrentValue);
}
else
{
double deltaMarket = targetMarket - marketBalanceAsBase;
OrderType otype;
double orderVolume;
double limit;
if (deltaMarket > 0)
{
// BUY
otype = OrderType.BUY;
orderVolume = deltaMarket / orderBook.CurrentAsk;
limit = orderBook.CurrentAsk;
}
else
{
// SELL
otype = OrderType.SELL;
orderVolume = -deltaMarket / orderBook.CurrentBid;
limit = orderBook.CurrentBid;
}
try {
//Order o = createLimitOrder(otype, Setup.CurrentValue.MarketSymbol, Setup.CurrentValue.BaseSymbol, orderVolume, limit);
//CurrentOrderID.CurrentValue = o.OrderID;
Log("Created balancing Order {0}", CurrentOrderID.CurrentValue);
} catch (Exception e){
Log("Exception creating Order: {0}", e.ToString());
}
}
}
DumpBalances();
}
}
public override void Save()
{
Setup.Save();
base.Save();
}
public override int SchedulingIntervall()
{
return 10;
}
public class WeightedIndicator{
public double Volume;
public double Weight;
}
public class SetupClass {
public bool Enabled;
public string MarketSymbol = "";
public string BaseSymbol = "";
public double BaseBalanceChange;
public double MarketBalanceChange;
public double DiffMargin = 0.1;
public WeightedIndicator[] Indicators = new WeightedIndicator[]{
new WeightedIndicator(),
new WeightedIndicator()
};
}
}
}

178
MarketValueBot.cs 100644
View File

@ -0,0 +1,178 @@
using System;
using sharp.json;
using System.IO;
using sharp.trading;
using sharp.trading.cache;
using sharp.extensions;
using sharp.tradebot;
namespace BigBot
{
public class MarketValueBot : TradingBot<BasicBotSetup>
{
public FileBackedJSONValue<SetupClass> Setup;
public FileBackedJSONValue<string> CurrentOrderID;
public MarketValueBot()
{
initialize();
}
private void initialize()
{
Setup = new FileBackedJSONValue<SetupClass>(Path.Combine(DataDirectory, "setup.json"));
CurrentOrderID = new FileBackedJSONValue<string>(Path.Combine(DataDirectory, "currentorder.json"));
}
public override void Prepare()
{
base.Prepare();
if (Setup.CurrentValue == null){
Setup.CurrentValue = new SetupClass();
}
}
public void Trade()
{
sharp.tradebot.TradeBotBalance balanceBase = getBalance(Setup.CurrentValue.BaseSymbol);
sharp.tradebot.TradeBotBalance balanceMarket = getBalance(Setup.CurrentValue.MarketSymbol);
if (CurrentOrderID.CurrentValue != null){
Order o = getOrder(CurrentOrderID.CurrentValue);
if (o.IsOpen)
{
TradingEnvironment.DefaultConnection.refreshOrder(o);
}
if (!o.IsOpen){
if (o.OrderType == OrderType.BUY){
balanceBase.CurrentBalance -= o.PayedFees + o.PayedPrice;
balanceMarket.CurrentBalance += o.FilledVolume;
} else {
balanceBase.CurrentBalance += o.PayedPrice - o.PayedFees;
balanceMarket.CurrentBalance -= o.FilledVolume;
}
Log("Order has been closed: {0}", o.ToString());
CurrentOrderID.CurrentValue = null;
Save();
}
}
if (Setup.CurrentValue.Enabled){
Log("Bot enabled");
/* Manage Balances */
if (Setup.CurrentValue.BaseBalanceChange != 0)
{
balanceBase.CurrentBalance += Setup.CurrentValue.BaseBalanceChange;
Setup.CurrentValue.BaseBalanceChange = 0;
Setup.Save();
}
if (Setup.CurrentValue.MarketBalanceChange != 0)
{
balanceMarket.CurrentBalance += Setup.CurrentValue.MarketBalanceChange;
Setup.CurrentValue.MarketBalanceChange = 0;
Setup.Save();
}
Market market = TradingEnvironment.DefaultConnection.openMarket(Setup.CurrentValue.MarketSymbol, Setup.CurrentValue.BaseSymbol);
OrderBook orderBook = market.getOrderBook();
System.Tuple<double,double> currentValues = orderBook.getVolumePrice(balanceMarket.CurrentBalance);
Log("Current Market Values: REBUY: {0,11:####0.00000000} {2} SELL: {1,11:####0.00000000} {2}", currentValues.Item1, currentValues.Item2, Setup.CurrentValue.BaseSymbol);
Log("Current Market Spread: {0,6:##0.00}%", ((currentValues.Item1 / currentValues.Item2)-1)*100);
double currentAbsDiff = Setup.CurrentValue.TargetValue - currentValues.Item2;
double currentDiff = currentAbsDiff / Setup.CurrentValue.TargetValue;
Log("Current Diff: {0,8:##0.0000} {1} [ {2,6:##0.00}% ] Limit: {3,6:##0.00}% / {4,6:##0.00}%", currentAbsDiff, Setup.CurrentValue.BaseSymbol, currentDiff * 100, Setup.CurrentValue.DiffMargin * 100, Setup.CurrentValue.DiffMarginBuy * 100);
if ((currentDiff > Setup.CurrentValue.DiffMarginBuy) || (-currentDiff > Setup.CurrentValue.DiffMargin))
{
if (CurrentOrderID.CurrentValue != null)
{
Log("Canceling old Order before creating new one.");
TradingEnvironment.DefaultConnection.cancelOrder(CurrentOrderID.CurrentValue);
} else
{
double diffMarket = currentAbsDiff / orderBook.CurrentBid;
if (diffMarket > 0){
// Buy
double window = orderBook.getVolumePrice(diffMarket).Item1 - orderBook.getVolumePrice(diffMarket).Item2;
double price = orderBook.getVolumePrice(diffMarket).Item1 + (Setup.CurrentValue.WindowLevelToBuy * window);
if (price >= balanceBase.CurrentBalance){
diffMarket *= balanceBase.CurrentBalance / price;
price = orderBook.getVolumePrice(diffMarket).Item1;
}
Log("Will buy {0,11:####0.00000000} {1} @ {2,11:####0.00000000} {3} = {4,11:####0.00000000} {3}", diffMarket, Setup.CurrentValue.MarketSymbol, orderBook.CurrentAsk, Setup.CurrentValue.BaseSymbol, price);
Order order = createLimitOrder(OrderType.BUY, Setup.CurrentValue.MarketSymbol, Setup.CurrentValue.BaseSymbol, diffMarket, orderBook.CurrentAsk);
CurrentOrderID.CurrentValue = order.OrderID;
} else {
// SELL
diffMarket = -diffMarket;
double window = orderBook.getVolumePrice(diffMarket).Item1 - orderBook.getVolumePrice(diffMarket).Item2;
double price = orderBook.getVolumePrice(diffMarket).Item1 + (Setup.CurrentValue.WindowLevelToBuy * window);
Log("Will sell {0,11:####0.00000000} {1} @ {2,11:####0.00000000} {3} = {4,11:####0.00000000} {3}", diffMarket, Setup.CurrentValue.MarketSymbol, orderBook.CurrentAsk, Setup.CurrentValue.BaseSymbol, price);
Order order = createLimitOrder(OrderType.SELL, Setup.CurrentValue.MarketSymbol, Setup.CurrentValue.BaseSymbol, diffMarket, orderBook.CurrentBid);
CurrentOrderID.CurrentValue = order.OrderID;
}
}
}
DumpBalances();
Log("--------------------------------------------------");
Log("Current Total: {0,11:####0.00000000} {1} ", balanceBase.CurrentBalance + currentValues.Item2, balanceBase.Currency);
Log("==================================================");
}
}
public override void Save()
{
Setup.Save();
base.Save();
}
public override int SchedulingIntervall()
{
return 15;
}
public class WeightedIndicator{
public double Volume;
public double Weight;
}
public class SetupClass {
public bool Enabled;
public string MarketSymbol = "";
public string BaseSymbol = "";
public double BaseBalanceChange;
public double MarketBalanceChange;
public double TargetValue = 0;
public double DiffMargin = 0.02;
public double DiffMarginBuy = 0.03;
public double WindowLevelToBuy = 0.1;
public double WindowLevelToSell = 0.8;
}
}
}

View File

@ -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("BigBot")]
[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("")]

260
SimpleBot.cs 100644
View File

@ -0,0 +1,260 @@
using System;
using System.Net.Sockets;
using sharp.trading;
namespace sharp.tradebot
{
public class SimpleBot : TradingBot<BasicBotSetup>
{
public SimpleBotSetup Setup { get; private set; } = new SimpleBotSetup();
TradeStep[] TradeSteps;
Market market;
public SimpleBot()
{
}
public override void Prepare()
{
base.Prepare();
Setup = loadJSON<SimpleBotSetup>("setup.json");
TradeSteps = loadJSON<TradeStep[]>("tradesteps.json");
checkTradeSteps();
}
void checkTradeSteps(){
if (TradeSteps.Length == 0){
TradeSteps = new TradeStep[Setup.HalfSteps*2];
for (int n = 0; n < TradeSteps.Length; n++){
TradeSteps[n] = new TradeStep();
TradeSteps[n].price_buy = Setup.CenterPrice * ((1.0 - Setup.HalfSpread) + ((double)n * Setup.HalfSpread / (Setup.HalfSteps)));
TradeSteps[n].price_sell = TradeSteps[n].price_buy * (1.0 + Setup.Offset);
TradeSteps[n].current_base_volume = StepBaseVolume();
TradeSteps[n].current_market_volume = StepMarketVolume();
}
}
}
double StepBaseVolume()
{
return Setup.ActiveBaseBalance / (2 * Setup.HalfSteps);
}
double StepMarketVolume()
{
return Setup.ActiveMarketBalance / (2 * Setup.HalfSteps);
}
public bool IsRunnable(){
if (Setup.marketSymbol == null || Setup.marketSymbol.Equals(""))
return false;
if (Setup.baseSymbol == null || Setup.baseSymbol.Equals(""))
return false;
return true;
}
public void Trade()
{
if (IsRunnable()){
market = TradingEnvironment.DefaultConnection.openMarket(Setup.marketSymbol, Setup.baseSymbol);
}
if (Setup.Enabled && IsRunnable()){
Log("SimpleBot is trading");
checkOrders();
} else if (IsRunnable()){
Console.WriteLine("SimpleBot instance is not enabled: {0}",this.UID);
Market market = TradingEnvironment.DefaultConnection.openMarket(Setup.marketSymbol, Setup.baseSymbol);
OrderBook orderbook = market.getOrderBook();
Console.WriteLine("Current Minimum Tradesize is {0:#0.00000000} {1}",market.MinimumTradeVolume,market.TradedSymbol);
Console.WriteLine("Current Best Bid: {0:#0.00000000} {1} Current best Ask: {2:#0.00000000} {3} , so at the Moment I would...",orderbook.CurrentBid,Setup.baseSymbol,orderbook.CurrentAsk,Setup.baseSymbol);
foreach (TradeStep step in TradeSteps)
{
if (step.price_buy < orderbook.CurrentAsk)
{
Console.WriteLine("Buy {0,8:##0.0000} {1} @ {2,11:##0.000000} {3} := {4,11:##0.000000} {5}", step.volume_to_buy(step.current_base_volume), Setup.marketSymbol, step.price_buy, Setup.baseSymbol, step.volume_to_buy(step.current_base_volume) * step.price_buy, Setup.baseSymbol);
}
}
foreach (TradeStep step in TradeSteps)
{
if (step.price_sell > orderbook.CurrentBid)
{
Console.WriteLine("Sell {0,8:##0.0000} {1} @ {2,11:##0.000000} {3} := {4,11:##0.000000} {5}", step.volume_to_sell(step.current_market_volume * Setup.CenterPrice), Setup.marketSymbol, step.price_sell, Setup.baseSymbol, step.volume_to_sell(step.current_market_volume * Setup.CenterPrice) * step.price_sell, Setup.baseSymbol);
}
}
} else {
Console.WriteLine("SimpleBot instance is not enabled and not ready to run: {0}",this.UID);
}
}
void Sell(TradeStep step){
if (!Setup.CancelAllOrders)
{
double volsell = step.volume_to_sell(step.current_market_volume * Setup.CenterPrice);
Order sell = createLimitOrder(OrderType.SELL, Setup.marketSymbol, Setup.baseSymbol, volsell, step.price_sell);
step.current_sell_order_id = sell.OrderID;
}
}
void Buy(TradeStep step)
{
if (!Setup.CancelAllOrders)
{
double volbuy = step.volume_to_buy(step.current_base_volume);
Order buyorder = createLimitOrder(OrderType.BUY, Setup.marketSymbol, Setup.baseSymbol, volbuy, step.price_buy);
step.current_buy_order_id = buyorder.OrderID;
}
}
void checkOrders()
{
foreach (TradeStep step in TradeSteps)
{
switch (step.getState())
{
case StepState.BUYING:
{
Order order = getOrder(step.current_buy_order_id);
if (!order.IsOpen)
{
double mRes = order.FilledVolume * (Setup.Offset - Setup.Fee) * Setup.Reserve;
Setup.ActiveBaseBalance -= order.PayedPrice;
Setup.ActiveBaseBalance -= order.PayedFees;
Setup.ActiveMarketBalance += order.FilledVolume - mRes;
Setup.ReservedMarketBalance += mRes;
step.current_buy_order_id = null;
Log("BUYED: {0} {1} @ {2} {3} Cost: {4} {5}", order.FilledVolume, Setup.marketSymbol, order.LimitPrice, Setup.baseSymbol, order.PayedPrice + order.PayedFees, Setup.baseSymbol);
Sell(step);
} else if (Setup.CancelAllOrders){
TradingEnvironment.DefaultConnection.cancelOrder(order);
}
}
break;
case StepState.SELLING:
{
Order order = getOrder(step.current_sell_order_id);
if (!order.IsOpen)
{
double bRes = order.PayedPrice * (Setup.Offset - Setup.Fee) * Setup.Reserve;
Setup.ActiveBaseBalance += order.PayedPrice - bRes;
Setup.ActiveBaseBalance -= order.PayedFees;
Setup.ReservedBaseBalance += bRes;
Setup.ActiveMarketBalance -= order.FilledVolume;
step.current_sell_order_id = null;
Log("SOLD: {0} {1} @ {2} {3} Cost: {4} {5}", order.FilledVolume, Setup.marketSymbol, order.LimitPrice, Setup.baseSymbol, order.PayedPrice + order.PayedFees, Setup.baseSymbol);
Buy(step);
} else if (Setup.CancelAllOrders){
TradingEnvironment.DefaultConnection.cancelOrder(order);
}
}
break;
case StepState.NONE:
if (step.price_buy < market.getOrderBook().CurrentAsk)
{
Buy(step);
}
else if (step.price_sell > market.getOrderBook().CurrentBid)
{
Sell(step);
}
break;
}
}
}
public override void Save()
{
if (Setup.Enabled)
{
saveJSON(Setup,"setup.json");
saveJSON(TradeSteps, "tradesteps.json");
}
base.Save();
}
public class SimpleBotSetup {
public bool Enabled = false;
public bool CancelAllOrders = false;
public string marketSymbol = "";
public string baseSymbol = "";
public double CenterPrice;
public double HalfSpread = 0.20;
public double Offset = 0.0125;
public int HalfSteps = 40;
public double ActiveMarketBalance = 0;
public double ReservedMarketBalance = 0;
public double ActiveBaseBalance = 0;
public double ReservedBaseBalance = 0;
public double Reserve = 0.5;
public double Fee = 0.0025;
}
public enum StepState {
NONE, SELLING, BUYING
}
public class TradeStep {
public double price_buy;
public double price_sell;
public double current_base_volume;
public double current_market_volume;
public string current_buy_order_id;
public string current_sell_order_id;
public double volume_to_buy(double base_volume){
return Math.Round(base_volume / price_buy, 4);
}
public double volume_to_sell(double base_volume)
{
return Math.Round(base_volume / price_sell, 4);
}
public StepState getState(){
if (current_buy_order_id != null){
return StepState.BUYING;
}
if (current_sell_order_id != null){
return StepState.SELLING;
}
return StepState.NONE;
}
public override string ToString()
{
return string.Format("[TradeStep buy={0,11:##.000000} sell={0,11:##.000000}]",price_buy,price_sell);
}
}
}
}

60
SmoothValue.cs 100644
View File

@ -0,0 +1,60 @@
using System;
using sharp.json.attributes;
namespace BigBot
{
[JSONClassPolicy( Policy = JSONPolicy.ATTRIBUTED)]
public class SmoothValue
{
[JSONField(Alias = "last")]
public double LastValue { get; private set; }
[JSONField( Alias = "current")]
public double CurrentValue { get; private set; }
[JSONField(Alias = "Kp")]
public double Kp { get; set; }
[JSONField(Alias = "sum")]
private double sum;
public SmoothValue()
{
}
public SmoothValue(double Kp)
{
this.Kp = Kp;
}
public void Clear()
{
this.sum = 0;
}
public void Set(double value){
this.sum = (value / this.Kp) - value;
this.CurrentValue = value;
this.LastValue = value;
}
public void Add(double value)
{
LastValue = CurrentValue;
this.sum += value;
CurrentValue = this.sum * this.Kp;
this.sum -= CurrentValue;
}
public double dT {
get {
return this.CurrentValue - this.LastValue;
}
}
public static implicit operator double(SmoothValue svalue){
return svalue.CurrentValue;
}
}
}

20
SpreadBot.cs 100644
View File

@ -0,0 +1,20 @@
using System;
namespace sharp.tradebot
{
public class SpreadBot: TradingBot<BasicBotSetup>
{
public SpreadBot()
{
}
public override int SchedulingIntervall()
{
return 30;
}
public class Setup {
}
}
}

68
StatisticalBot.cs 100644
View File

@ -0,0 +1,68 @@
using System;
using sharp.json;
using sharp.trading;
using System.IO;
namespace sharp.tradebot
{
public class StatisticalBot : TradingBot<BasicBotSetup>
{
FileBackedJSONValue<BotSetup> Setup;
public StatisticalBot()
{
initialize();
}
private void initialize()
{
Setup = new FileBackedJSONValue<BotSetup>(Path.Combine(DataDirectory, "setup.json"));
}
public override void Prepare()
{
base.Prepare();
if (Setup.CurrentValue == null){
Setup.CurrentValue = new BotSetup();
Setup.Save();
}
}
public void Trade()
{
if (Setup.CurrentValue.Enabled)
{
Market market = TradingEnvironment.DefaultConnection.openMarket(Setup.CurrentValue.MarketSymbol, Setup.CurrentValue.BaseSymbol);
OrderBook orderbook = market.getOrderBook();
OrderbookVolume[] obvolumes = orderbook.calculateVolumes(Setup.CurrentValue.OrderBookIndicationVolumina);
Log("Current Orderbook Indications:");
foreach (OrderbookVolume ovol in obvolumes)
{
Log("Volume: {0,15:#########0.0000} {1} BUY: {2,11:####0.00000000} {3} SELL: {4,11:####0.00000000} {3}", ovol.VolumeBuy, Setup.CurrentValue.MarketSymbol, ovol.PriceBuy, Setup.CurrentValue.BaseSymbol, ovol.PriceSell);
Log(" RATIO: {0,11:####0.00000000} AVERAGE: {1,11:####0.00000000} {2}", ovol.PriceBuy / ovol.PriceSell, (ovol.AverageUnitPriceBuy + ovol.AverageUnitPriceSell) / 2, Setup.CurrentValue.BaseSymbol);
}
}
}
public override int SchedulingIntervall()
{
return 60;
}
class BotSetup {
public bool Enabled;
public string MarketSymbol = "";
public string BaseSymbol = "";
public double[] OrderBookIndicationVolumina = new double[] { 10, 25, 50, 100, 200, 400, 800, 1600, 3200 };
}
}
}

151
TargetValueBot.cs 100644
View File

@ -0,0 +1,151 @@
using System;
using sharp.json;
using System.IO;
using sharp.trading;
using sharp.trading.cache;
using sharp.extensions;
using sharp.json.attributes;
using sharp.tradebot;
namespace BigBot
{
[JSONClassPolicy(Policy = JSONPolicy.ATTRIBUTED)]
public class TargetValueBot : TradingBot<SetupClass>
{
[JSONField]
public string CurrentOrderID;
public override void Prepare()
{
base.Prepare();
TradingBotEnvironment.RegisterPeriodic(Trade,10);
}
public override void Unprepare()
{
TradingBotEnvironment.UnregisterPeriodic(Trade);
base.Unprepare();
}
public void Trade()
{
TradeBotBalance balanceBase = getBalance(BasicSetup.BaseSymbol);
TradeBotBalance balanceMarket = getBalance(BasicSetup.MarketSymbol);
if (BasicSetup.Enabled){
Log("TargetValueBot V2 is trading...");
OrderBook orderBook = BotMarket.getOrderBook();
double testVolume = balanceMarket.CurrentBalance;
if (testVolume == 0){
testVolume = 1;
}
System.Tuple<double,double> currentValues = orderBook.getVolumePrice(testVolume);
// Log("Current Market Values: REBUY: {0,11:####0.00000000} {2} SELL: {1,11:####0.00000000} {2}", currentValues.Item1, currentValues.Item2, BasicSetup.BaseSymbol);
//1 Log("Current Market Spread: {0,6:##0.00}%", ((currentValues.Item1 / currentValues.Item2)-1)*100);
double currentMarketValue = currentValues.Item2;
double currentUnitValue = currentMarketValue / testVolume;
double alpha = BasicSetup.TargetPrice / currentUnitValue;
double beta = Math.Pow(alpha, BasicSetup.TargetExponent);
double finalTargetValue = BasicSetup.TargetValue * beta;
if (balanceMarket.CurrentBalance <= 0){
currentMarketValue = 0;
}
double currentAbsDiff = finalTargetValue - currentMarketValue;
double currentDiff = currentAbsDiff / finalTargetValue;
Log("Current Market Balance: {0,10:###0.0000} {1} Current Market Value: {2,10:###0.0000} {3}", balanceMarket.CurrentBalance, balanceMarket.Currency, currentMarketValue, balanceBase.Currency);
Log("Current Market Price (bid): {0,10:###0.0000} {1}",currentUnitValue,balanceBase.Currency);
Log("Current Target Value: {0,10:###0.0000} {1} Target Value Diff: {2,10:###0.0000} {1} [ {3,6:##0.00}% ]", finalTargetValue, balanceBase.Currency, currentAbsDiff,currentDiff * 100);
if (!CurrentOrderID.IsNull())
{
Order order = getOrder(CurrentOrderID);
if (!order.IsOpen)
{
CurrentOrderID = null;
}
}
if ((currentDiff > BasicSetup.MarginBuy) || (-currentDiff > BasicSetup.MarginSell))
{
if (!CurrentOrderID.IsNull()){
Log("Canceling old Order before creating new one.");
TradingEnvironment.DefaultConnection.cancelOrder(CurrentOrderID);
} else
{
double diffMarket = currentAbsDiff / orderBook.CurrentBid;
if (diffMarket > 0){
// Buy
double window = orderBook.getVolumePrice(diffMarket).Item1 - orderBook.getVolumePrice(diffMarket).Item2;
double price = orderBook.getVolumePrice(diffMarket).Item1 + (BasicSetup.WindowLevelToBuy * window);
if (price >= balanceBase.CurrentBalance){
diffMarket *= balanceBase.CurrentBalance / price;
price = orderBook.getVolumePrice(diffMarket).Item1;
}
Log("Will buy {0,11:####0.00000000} {1} @ {2,11:####0.00000000} {3} = {4,11:####0.00000000} {3}", diffMarket, BasicSetup.MarketSymbol, orderBook.CurrentAsk, BasicSetup.BaseSymbol, price);
Order order = createLimitOrder(OrderType.BUY, BasicSetup.MarketSymbol, BasicSetup.BaseSymbol, diffMarket, orderBook.CurrentAsk);
if (!order.IsNull()){
CurrentOrderID = order.OrderID;
}
} else {
// SELL
diffMarket = -diffMarket;
double window = orderBook.getVolumePrice(diffMarket).Item1 - orderBook.getVolumePrice(diffMarket).Item2;
double price = orderBook.getVolumePrice(diffMarket).Item1 + (BasicSetup.WindowLevelToBuy * window);
Log("Will sell {0,11:####0.00000000} {1} @ {2,11:####0.00000000} {3} = {4,11:####0.00000000} {3}", diffMarket, BasicSetup.MarketSymbol, orderBook.CurrentBid, BasicSetup.BaseSymbol, price);
Order order = createLimitOrder(OrderType.SELL, BasicSetup.MarketSymbol, BasicSetup.BaseSymbol, diffMarket, orderBook.CurrentBid);
if (!order.IsNull()){
CurrentOrderID = order.OrderID;
}
}
}
}
DumpBalances();
Save();
}
}
public override int SchedulingIntervall()
{
return 15;
}
public class WeightedIndicator{
public double Volume;
public double Weight;
}
}
public class SetupClass : BasicBotSetup
{
public double TargetValue = 0;
public double TargetPrice = 0;
public double TargetExponent = 3;
public double MarginSell = 0.02;
public double MarginBuy = 0.02;
public double WindowLevelToBuy = 0.1;
public double WindowLevelToSell = 0.8;
}
}