Skip to content

Commit 18c8e8e

Browse files
committed
Optimize gemini symbol metadata
1 parent d3e5a86 commit 18c8e8e

File tree

1 file changed

+82
-3
lines changed

1 file changed

+82
-3
lines changed

src/ExchangeSharp/API/Exchanges/Gemini/ExchangeGeminiAPI.cs

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The above copyright notice and this permission notice shall be included in all c
1818
using System.Text;
1919
using System.Threading.Tasks;
2020
using System.Web;
21+
using System.Xml;
2122

2223
using Newtonsoft.Json;
2324
using Newtonsoft.Json.Linq;
@@ -96,10 +97,88 @@ protected override async Task<IEnumerable<string>> OnGetMarketSymbolsAsync()
9697

9798
protected internal override async Task<IEnumerable<ExchangeMarket>> OnGetMarketSymbolsMetadataAsync()
9899
{
99-
Logger.Warn("Fetching gemini symbol metadata, this may take a minute...");
100+
List<ExchangeMarket> markets = new List<ExchangeMarket>();
101+
102+
try
103+
{
104+
string html = await RequestMaker.MakeRequestAsync("/rest-api", "https://docs.gemini.com");
105+
int startPos = html.IndexOf("<h1 id=\"symbols-and-minimums\">Symbols and minimums</h1>");
106+
if (startPos >= 0)
107+
{
108+
startPos = html.IndexOf("<tbody>", startPos);
109+
if (startPos >= 0)
110+
{
111+
int endPos = html.IndexOf("</tbody>", startPos);
112+
string table = html.Substring(startPos, endPos - startPos + "</tbody>".Length);
113+
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + table;
114+
XmlDocument doc = new XmlDocument();
115+
doc.LoadXml(xml);
116+
if (doc.ChildNodes.Count > 1)
117+
{
118+
XmlNode root = doc.ChildNodes.Item(1);
119+
foreach (XmlNode tr in root.ChildNodes)
120+
{
121+
// <tr>
122+
// <th>Symbol</th>
123+
// <th>Minimum Order Size</th>
124+
// <th>Tick Size</th>
125+
// <th>Quote Currency Price Increment</th>
126+
127+
// <td>btcusd</td>
128+
// <td>0.00001 BTC (1e-5)</td>
129+
// <td>0.00000001 BTC (1e-8)</td>
130+
// <td>0.01 USD</td>
131+
// </tr>
132+
133+
if (tr.ChildNodes.Count == 4)
134+
{
135+
ExchangeMarket market = new ExchangeMarket { IsActive = true };
136+
XmlNode symbolNode = tr.ChildNodes.Item(0);
137+
XmlNode minOrderSizeNode = tr.ChildNodes.Item(1);
138+
XmlNode tickSizeNode = tr.ChildNodes.Item(2);
139+
XmlNode incrementNode = tr.ChildNodes.Item(3);
140+
string symbol = symbolNode.InnerText;
141+
int minOrderSizePos = minOrderSizeNode.InnerText.IndexOf(' ');
142+
if (minOrderSizePos < 0)
143+
{
144+
throw new ArgumentException("Min order size text does not have a space after the number");
145+
}
146+
decimal minOrderSize = minOrderSizeNode.InnerText.Substring(0, minOrderSizePos).ConvertInvariant<decimal>();
147+
int tickSizePos = tickSizeNode.InnerText.IndexOf(' ');
148+
if (tickSizePos < 0)
149+
{
150+
throw new ArgumentException("Tick size text does not have a space after the number");
151+
}
152+
decimal tickSize = tickSizeNode.InnerText.Substring(0, tickSizePos).ConvertInvariant<decimal>();
153+
int incrementSizePos = incrementNode.InnerText.IndexOf(' ');
154+
if (incrementSizePos < 0)
155+
{
156+
throw new ArgumentException("Increment size text does not have a space after the number");
157+
}
158+
decimal incrementSize = incrementNode.InnerText.Substring(0, incrementSizePos).ConvertInvariant<decimal>();
159+
market.MarketSymbol = symbol;
160+
market.BaseCurrency = symbol.Substring(0, symbol.Length - 3);
161+
market.QuoteCurrency = symbol.Substring(symbol.Length - 3);
162+
market.MinTradeSize = minOrderSize;
163+
market.QuantityStepSize = tickSize;
164+
market.PriceStepSize = incrementSize;
165+
markets.Add(market);
166+
}
167+
}
168+
return markets;
169+
}
170+
}
171+
}
172+
}
173+
catch (Exception ex)
174+
{
175+
Logger.Error(ex, "Failed to parse gemini symbol metadata web page, falling back to per symbol query...");
176+
}
177+
178+
// slow way, fetch each symbol one by one, gemini api epic fail
179+
Logger.Warn("Fetching gemini symbol metadata per symbol, this may take a minute...");
100180

101181
string[] symbols = (await GetMarketSymbolsAsync()).ToArray();
102-
List<ExchangeMarket> markets = new List<ExchangeMarket>();
103182
List<Task> tasks = new List<Task>();
104183
foreach (string symbol in symbols)
105184
{
@@ -115,7 +194,7 @@ protected internal override async Task<IEnumerable<ExchangeMarket>> OnGetMarketS
115194
BaseCurrency = token["base_currency"].ToStringInvariant(),
116195
IsActive = token["status"].ToStringInvariant().Equals("open", StringComparison.OrdinalIgnoreCase),
117196
MarketSymbol = token["symbol"].ToStringInvariant(),
118-
MinTradeSize = token["min_order_Size"].ConvertInvariant<decimal>(),
197+
MinTradeSize = token["min_order_size"].ConvertInvariant<decimal>(),
119198
QuantityStepSize = token["tick_size"].ConvertInvariant<decimal>(),
120199
QuoteCurrency = token["quote_currency"].ToStringInvariant(),
121200
PriceStepSize = token["quote_increment"].ConvertInvariant<decimal>()

0 commit comments

Comments
 (0)