Skip to content

Commit 6b8aa38

Browse files
konardclaude
andcommitted
Implement API abstraction layer to make bot independent of Tinkoff API
This implementation introduces a comprehensive abstraction layer that decouples the trading bot from the Tinkoff API, addressing the issue of API instability. Key Changes: - Created ITradingApiProvider interface to abstract all trading operations - Implemented TinkoffApiProvider as a wrapper around Tinkoff InvestApi - Added MockApiProvider for testing without real API calls - Introduced configuration-based provider selection - Created interfaces for all trading data structures (IAccount, IInstrument, IOrder, etc.) - Used custom enums to avoid namespace conflicts with provider APIs - Refactored TradingService to use the abstraction layer Benefits: - Reduced dependency risk - no longer tied to single API provider - Easy testing with mock provider - Provider flexibility via configuration - Future-proof architecture for adding new trading APIs - API instability isolation to specific provider implementations Files added: - Interfaces/ - Complete abstraction layer interfaces - Providers/TinkoffApiProvider.cs - Tinkoff implementation - Providers/Tinkoff/ - Tinkoff-specific wrapper classes - Providers/MockApiProvider.cs - Mock implementation for testing - AbstractTradingService.cs - Refactored service using abstraction - Configuration files and examples 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 96b0023 commit 6b8aa38

24 files changed

+2008
-5
lines changed

csharp/TraderBot/AbstractTradingService.cs

Lines changed: 812 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace TraderBot;
2+
3+
public class ApiProviderSettings
4+
{
5+
public string Provider { get; set; } = "Tinkoff";
6+
}
7+
8+
public class InvestApiSettings
9+
{
10+
public string? AccessToken { get; set; }
11+
public string? AppName { get; set; }
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface IAccount
4+
{
5+
string Id { get; }
6+
string Name { get; }
7+
DateTime OpenedDate { get; }
8+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface IInstrument
4+
{
5+
string Figi { get; }
6+
string Ticker { get; }
7+
int Lot { get; }
8+
decimal MinPriceIncrement { get; }
9+
TradingInstrumentType InstrumentType { get; }
10+
}
11+
12+
public enum TradingInstrumentType
13+
{
14+
Etf,
15+
Shares
16+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface IOperation
4+
{
5+
string Id { get; }
6+
TradingOperationType OperationType { get; }
7+
DateTime Date { get; }
8+
long Quantity { get; }
9+
decimal Price { get; }
10+
long QuantityRest { get; }
11+
IEnumerable<ITrade>? Trades { get; }
12+
long GetActualQuantity();
13+
}
14+
15+
public enum TradingOperationType
16+
{
17+
Buy,
18+
Sell
19+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface IOrder
4+
{
5+
string OrderId { get; }
6+
string Figi { get; }
7+
TradingOrderDirection Direction { get; }
8+
long LotsRequested { get; set; }
9+
decimal InitialSecurityPrice { get; }
10+
decimal InitialOrderPrice { get; }
11+
}
12+
13+
public interface IOrderRequest
14+
{
15+
string OrderId { get; }
16+
string AccountId { get; }
17+
TradingOrderDirection Direction { get; }
18+
TradingOrderType OrderType { get; }
19+
string Figi { get; }
20+
long Quantity { get; }
21+
decimal Price { get; }
22+
}
23+
24+
public interface IOrderResponse
25+
{
26+
string OrderId { get; }
27+
string Figi { get; }
28+
TradingOrderDirection Direction { get; }
29+
long LotsRequested { get; }
30+
decimal InitialSecurityPrice { get; }
31+
}
32+
33+
public interface ICancelOrderResponse
34+
{
35+
string OrderId { get; }
36+
}
37+
38+
public enum TradingOrderDirection
39+
{
40+
Buy,
41+
Sell
42+
}
43+
44+
public enum TradingOrderType
45+
{
46+
Limit,
47+
Market
48+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface IOrderBookStream : IAsyncEnumerable<IOrderBook>
4+
{
5+
}
6+
7+
public interface IOrderBook
8+
{
9+
string Figi { get; }
10+
IEnumerable<IOrderBookEntry> Bids { get; }
11+
IEnumerable<IOrderBookEntry> Asks { get; }
12+
}
13+
14+
public interface IOrderBookEntry
15+
{
16+
decimal Price { get; }
17+
long Quantity { get; }
18+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface IPosition
4+
{
5+
string Figi { get; }
6+
decimal Balance { get; }
7+
}
8+
9+
public interface IPortfolio
10+
{
11+
IEnumerable<IPortfolioPosition> Positions { get; }
12+
IEnumerable<IMoneyValue> Money { get; }
13+
IEnumerable<IMoneyValue> Blocked { get; }
14+
}
15+
16+
public interface IPortfolioPosition
17+
{
18+
string Figi { get; }
19+
decimal Quantity { get; }
20+
}
21+
22+
public interface IMoneyValue
23+
{
24+
string Currency { get; }
25+
decimal Value { get; }
26+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface ITradesStream : IAsyncEnumerable<ITradeData>
4+
{
5+
}
6+
7+
public interface ITradeData
8+
{
9+
TradeDataType DataType { get; }
10+
IOrderTrades? OrderTrades { get; }
11+
}
12+
13+
public interface IOrderTrades
14+
{
15+
string OrderId { get; }
16+
TradingOrderDirection Direction { get; }
17+
IEnumerable<ITrade> Trades { get; }
18+
}
19+
20+
public interface ITrade
21+
{
22+
long Quantity { get; }
23+
decimal Price { get; }
24+
DateTime DateTime { get; }
25+
}
26+
27+
public enum TradeDataType
28+
{
29+
OrderTrades,
30+
Ping
31+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace TraderBot.Interfaces;
2+
3+
public interface ITradingApiProvider
4+
{
5+
Task InitializeAsync();
6+
Task<IEnumerable<IAccount>> GetAccountsAsync();
7+
Task<IInstrument> GetInstrumentAsync(string ticker, TradingInstrumentType instrumentType);
8+
Task<IOrderBookStream> SubscribeToOrderBookAsync(string figi, int depth);
9+
Task<ITradesStream> SubscribeToTradesAsync(string accountId);
10+
Task<IEnumerable<IOrder>> GetOrdersAsync(string accountId);
11+
Task<IEnumerable<IPosition>> GetPositionsAsync(string accountId);
12+
Task<IPortfolio> GetPortfolioAsync(string accountId);
13+
Task<IEnumerable<IOperation>> GetOperationsAsync(string accountId, string figi, DateTime from, DateTime to);
14+
Task<IOrderResponse> PlaceOrderAsync(IOrderRequest orderRequest);
15+
Task<ICancelOrderResponse> CancelOrderAsync(string accountId, string orderId);
16+
}

0 commit comments

Comments
 (0)