Skip to content

Commit

Permalink
Merge pull request #21 from drift-labs/sina/update-funding-rate-docs
Browse files Browse the repository at this point in the history
Add examples for fetching historical trades + funding rate
  • Loading branch information
SinaKhalili authored Oct 11, 2024
2 parents 3fd4a43 + 91e775e commit eba09df
Show file tree
Hide file tree
Showing 2 changed files with 291 additions and 2 deletions.
85 changes: 85 additions & 0 deletions source/includes/_data_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,97 @@ Example: [https://data.api.drift.trade/contracts](https://data.api.drift.trade/c

Returns the last 30 days of funding rates by marketName or marketIndex.

```python
import requests

def get_funding_rates(market_symbol='SOL-PERP'):
url = f'https://data.api.drift.trade/fundingRates'
params = {'marketName': market_symbol}

response = requests.get(url, params=params)
return response.json()['fundingRates']

# Example usage, print the funding rates for SOL-PERP
market_symbol = 'SOL-PERP'
rates = get_funding_rates(market_symbol)

print(f"Funding Rates for {market_symbol}:")
for rate in rates:
funding_rate = float(rate['fundingRate']) / 1e9
# ... any logic here, for example...
print(f"Slot: {rate['slot']}, Funding Rate: {funding_rate:.9f}")

```
```typescript
interface FundingRate {
slot: number;
fundingRate: string;
// Other fields... (view the response section for the full list)
}

async function getFundingRates(marketSymbol: string = 'SOL-PERP'): Promise<FundingRate[]> {
const url = `https://data.api.drift.trade/fundingRates?marketName=${marketSymbol}`;

try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.fundingRates;
} catch (error) {
console.error('Error fetching funding rates:', error);
return [];
}
}

async function main() {
const marketSymbol = 'SOL-PERP';
const rates = await getFundingRates(marketSymbol);

console.log(`Funding Rates for ${marketSymbol}:`);
rates.forEach(rate => {
const fundingRate = parseFloat(rate.fundingRate) / 1e9;
// ... any logic here, for example...
console.log(`Slot: ${rate.slot}, Funding Rate: ${fundingRate.toFixed(9)}`);
});
}

main().catch(error => console.error('An error occurred:', error));
```

<aside class="notice">
The funding rate is returned as a string and needs to be divided by 1e9 to get the actual rate.
</aside>


| Parameter | Description | Optional | Values |
| ---------------- | ------------------------------------------------ | -------- | --------------------------------------------------- |
| marketName or marketIndex | The market name or index for the perp market | NO | |

Example: [https://data.api.drift.trade/fundingRates?marketName=SOL-PERP](https://data.api.drift.trade/fundingRates?marketName=SOL-PERP)

### Response
The response is a json object with a `fundingRates` array. Each funding rate entry contains the following fields:

| Field | Type | Description |
|-------|------|-------------|
| `txSig` | string | Transaction signature |
| `slot` | integer | Slot number |
| `ts` | string | Timestamp |
| `recordId` | string | Record identifier |
| `marketIndex` | integer | Market index |
| `fundingRate` | string | Funding rate (divide by 1e9 for actual rate) |
| `cumulativeFundingRateLong` | string | Cumulative funding rate for long positions |
| `cumulativeFundingRateShort` | string | Cumulative funding rate for short positions |
| `oraclePriceTwap` | string | Oracle price time-weighted average price |
| `markPriceTwap` | string | Mark price time-weighted average price |
| `fundingRateLong` | string | Funding rate for long positions |
| `fundingRateShort` | string | Funding rate for short positions |
| `periodRevenue` | string | Revenue for the period |
| `baseAssetAmountWithAmm` | string | Base asset amount with AMM |
| `baseAssetAmountWithUnsettledLp` | string | Base asset amount with unsettled LP |



## `GET /DRIFT/`
Expand Down
208 changes: 206 additions & 2 deletions source/includes/_historicaldata.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,217 @@ mainnet-beta: `https://drift-historical-data-v2.s3.eu-west-1.amazonaws.com/prog
| candleResolution | | 1M |


## Examples

Get historical trades on `SOL-PERP` for August 5, 2023:
## Example: Trades for market
```python
import requests


URL_PREFIX = 'https://drift-historical-data-v2.s3.eu-west-1.amazonaws.com/program/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH'

market_symbol = 'SOL-PERP'
year = '2024'
month = '01'
day = '01'

# Method 1: using pandas (this is the easiest and fastest way)
import pandas as pd
df = pd.read_csv(f'{URL_PREFIX}/market/{market_symbol}/tradeRecords/{year}/{year}{month}{day}')
print(df)

# Method 2: using csv reader
import csv
from io import StringIO

response = requests.get(f'{URL_PREFIX}/market/{market_symbol}/tradeRecords/{year}/{year}{month}{day}')
response.raise_for_status()

csv_data = StringIO(response.text)
reader = csv.reader(csv_data)
for row in reader:
print(row)

```

```typescript
import { parse } from 'csv-parse/sync';

const URL_PREFIX = 'https://drift-historical-data-v2.s3.eu-west-1.amazonaws.com/program/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH';

async function fetchAndParseCSV(marketSymbol: string, year: string, month: string, day: string): Promise<void> {
const url = `${URL_PREFIX}/market/${marketSymbol}/tradeRecords/${year}/${year}${month}${day}`;

try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const csvText = await response.text();
const records = parse(csvText, {
skip_empty_lines: true
});

records.forEach((row: string[]) => {
console.log(row);
});
} catch (error) {
console.error('Error fetching or parsing CSV:', error);
}
}

async function main() {
const marketSymbol = 'SOL-PERP';
const year = '2024';
const month = '01';
const day = '01';

await fetchAndParseCSV(marketSymbol, year, month, day);
}

main().catch(error => console.error('An error occurred:', error));
```

Get historical trades on `SOL-PERP` for a given date (ex. 2024-01-01):
```
https://drift-historical-data-v2.s3.eu-west-1.amazonaws.com/program/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH/market/SOL-PERP/tradeRecords/2024/20240101
```


## Example: Trades for date range
```python
import requests
import csv
from io import StringIO
from datetime import date, timedelta
import pandas as pd

URL_PREFIX = 'https://drift-historical-data-v2.s3.eu-west-1.amazonaws.com/program/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH'

# Method 1: using pandas
def get_trades_for_range_pandas(account_key, start_date, end_date):
all_trades = []
current_date = start_date
while current_date <= end_date:
year = current_date.year
month = current_date.month
day = current_date.day
url = f"{URL_PREFIX}/user/{account_key}/tradeRecords/{year}/{year}{month:02}{day:02}"

try:
df = pd.read_csv(url)
all_trades.append(df)
except requests.exceptions.RequestException as e:
print(f"Error fetching data for {current_date}: {e}")
except pd.errors.EmptyDataError:
print(f"No data available for {current_date}")

current_date += timedelta(days=1)

if all_trades:
return pd.concat(all_trades, ignore_index=True)
else:
return pd.DataFrame()

# Method 2: using csv reader
def get_trades_for_range_csv(account_key, start_date, end_date):
all_trades = []
current_date = start_date
while current_date <= end_date:
year = current_date.year
month = current_date.month
day = current_date.day
url = f"{URL_PREFIX}/user/{account_key}/tradeRecords/{year}/{year}{month:02}{day:02}"
response = requests.get(url)
response.raise_for_status()

csv_data = StringIO(response.text)
reader = csv.reader(csv_data)
for row in reader:
all_trades.append(row)

current_date += timedelta(days=1)

return all_trades


# Example usage
account_key = "<Some Account Key>"
start_date = date(2024, 1, 24)
end_date = date(2024, 1, 26)

trades = get_trades_for_range(account_key, start_date, end_date)
```

```typescript
import { parse } from 'csv-parse/sync';

const URL_PREFIX = 'https://drift-historical-data-v2.s3.eu-west-1.amazonaws.com/program/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH';

interface Trade {
// Define the structure of a trade record here
// For example:
// date: string;
// amount: number;
// price: number;
[key: string]: any;
}

async function getTradesForRange(accountKey: string, startDate: Date, endDate: Date): Promise<Trade[]> {
const allTrades: Trade[] = [];
let currentDate = new Date(startDate);

while (currentDate <= endDate) {
const year = currentDate.getFullYear();
const month = (currentDate.getMonth() + 1).toString().padStart(2, '0');
const day = currentDate.getDate().toString().padStart(2, '0');

const url = `${URL_PREFIX}/user/${accountKey}/tradeRecords/${year}/${year}${month}${day}`;

try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const csvText = await response.text();
const records = parse(csvText, {
skip_empty_lines: true,
columns: true
});

allTrades.push(...records);
} catch (error) {
console.error(`Error fetching or parsing CSV for ${year}-${month}-${day}:`, error);
}

currentDate.setDate(currentDate.getDate() + 1);
}

return allTrades;
}

async function main() {
const accountKey = "<Some Account Key>";
const startDate = new Date(2024, 0, 24); // Note: month is 0-indexed in JavaScript
const endDate = new Date(2024, 0, 26);

try {
const trades = await getTradesForRange(accountKey, startDate, endDate);
console.log(`Total trades fetched: ${trades.length}`);
console.log('First few trades:', trades.slice(0, 5));
} catch (error) {
console.error('An error occurred:', error);
}
}

main();
```

> Note: To speed this up, you could download the data in parallel (Promise.all or asyncio).
We can write a script to download all the data, one by one, for a given account in a given date range.

## Records Columns

Below are definitions of the columns in each record type.
Expand Down

0 comments on commit eba09df

Please sign in to comment.