Added saving to database

This commit is contained in:
askeluv
2019-02-12 12:30:10 +08:00
parent 7ad4cb0078
commit c0a2f429b6
8 changed files with 98 additions and 52 deletions

View File

@@ -0,0 +1,28 @@
import {MigrationInterface, QueryRunner, Table} from "typeorm";
const slippage = new Table({
name: 'raw.slippage',
columns: [
{ name: 'observed_timestamp', type: 'bigint', isPrimary: true },
{ name: 'symbol', type: 'varchar', isPrimary: true },
{ name: 'exchange', type: 'varchar', isPrimary: true },
{ name: 'usd_amount', type: 'numeric', isPrimary: true },
{ name: 'token_amount', type: 'numeric', isNullable: false },
{ name: 'avg_price_in_eth_buy', type: 'numeric', isNullable: true },
{ name: 'avg_price_in_eth_sell', type: 'numeric', isNullable: true },
{ name: 'slippage', type: 'numeric', isNullable: true },
],
});
export class CreateSlippageTable1549856835629 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.createTable(slippage);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.dropTable(slippage);
}
}

View File

@@ -30,7 +30,6 @@ export class EdpsSource {
* Call Ethereum DEX Price Service API.
*/
public async getEdpsAsync(direction: string, symbol: string, amount: number): Promise<Map<string, EdpsExchange>> {
logUtils.log('Getting EDPS response');
const edpsUrl = `${EDPS_BASE_URL}/${direction}?symbol=${symbol}&amount=${amount}`;
const resp = await fetchAsync(edpsUrl);
const respJson: EdpsResponse = await resp.json();
@@ -40,7 +39,6 @@ export class EdpsSource {
allExchanges.set(key, entry[key]);
}
}
logUtils.log(`Got ${allExchanges.size} exchanges.`);
return allExchanges;
}
}
@@ -50,7 +48,6 @@ export class PriceSource {
* Call CryptoCompare Price API to get USD price of token.
*/
public async getUsdPriceAsync(symbol: string): Promise<number> {
logUtils.log(`Fetching USD price for ${symbol}`);
const priceUrl = `${PRICE_BASE_URL}&fsym=${symbol}`
const resp = await fetchAsync(priceUrl);
const respJson: PriceResponse = await resp.json();

View File

@@ -9,7 +9,7 @@ export { ExchangeCancelUpToEvent } from './exchange_cancel_up_to_event';
export { ExchangeFillEvent } from './exchange_fill_event';
export { OHLCVExternal } from './ohlcv_external';
export { Relayer } from './relayer';
export { SlippageRecord } from './slippage';
export { Slippage } from './slippage';
export { SraOrder } from './sra_order';
export { SraOrdersObservedTimeStamp, createObservedTimestampForOrder } from './sra_order_observed_timestamp';
export { TokenMetadata } from './token_metadata';

View File

@@ -1,15 +1,22 @@
import { Column, Entity, PrimaryColumn } from 'typeorm';
import { numberToBigIntTransformer } from '../utils';
@Entity({ name: 'slippage_records', schema: 'raw' })
export class SlippageRecord {
@PrimaryColumn({ name: 'time', type: 'number'})
public time!: number;
@Entity({ name: 'slippage', schema: 'raw' })
export class Slippage {
@PrimaryColumn({ name: 'observed_timestamp', type: 'bigint', transformer: numberToBigIntTransformer})
public observedTimestamp!: number;
@PrimaryColumn({ name: 'symbol' })
public symbol!: string;
@PrimaryColumn({ name: 'exchange' })
public exchange!: string;
@PrimaryColumn({ name: 'usdAmount', type: 'number' })
@PrimaryColumn({ name: 'usd_amount', type: 'numeric' })
public usdAmount!: number;
@Column({ name: 'slippage', type: 'number' })
public slippage!: number;
@PrimaryColumn({ name: 'token_amount', type: 'numeric' })
public tokenAmount!: number;
@PrimaryColumn({ name: 'avg_price_in_eth_sell', type: 'numeric' })
public avgPriceInEthSell?: number;
@PrimaryColumn({ name: 'avg_price_in_eth_buy', type: 'numeric' })
public avgPriceInEthBuy?: number;
@Column({ name: 'slippage', type: 'numeric' })
public slippage?: number;
}

View File

@@ -14,7 +14,7 @@ import {
ExchangeFillEvent,
OHLCVExternal,
Relayer,
SlippageRecord,
Slippage,
SraOrder,
SraOrdersObservedTimeStamp,
TokenMetadata,
@@ -36,7 +36,7 @@ const entities = [
ERC20ApprovalEvent,
OHLCVExternal,
Relayer,
SlippageRecord,
Slippage,
SraOrder,
SraOrdersObservedTimeStamp,
TokenMetadata,

View File

@@ -2,11 +2,11 @@ import { BigNumber } from '@0x/utils';
import * as R from 'ramda';
import { EdpsExchange } from '../../data_sources/slippage';
import { SlippageRecord } from '../../entities';
import { Slippage } from '../../entities';
import { symbol } from 'prop-types';
/**
* Calculates slippage and returns SlippageRecord entity.
* Calculates slippage and returns Slippage entity.
*
* @param usdAmount
* @param exchange
@@ -18,18 +18,17 @@ import { symbol } from 'prop-types';
buyEdps: Map<string, EdpsExchange>, sellEdps: Map<string, EdpsExchange>) {
const b = buyEdps.get(exchange);
const s = sellEdps.get(exchange);
const slippage = new Slippage();
if (b && s && b.avgPrice && s.avgPrice) {
var slippage = (b.avgPrice - s.avgPrice) / b.avgPrice;
const observedTimestamp = Date.now();
const slippageRecord = new SlippageRecord();
slippageRecord.time = observedTimestamp;
slippageRecord.symbol = b.tokenSymbol;
slippageRecord.exchange = exchange;
slippageRecord.usdAmount = usdAmount;
slippageRecord.slippage = slippage;
return slippageRecord;
}
else {
return null;
slippage.observedTimestamp = b.timestamp;
slippage.symbol = b.tokenSymbol;
slippage.exchange = exchange;
slippage.usdAmount = usdAmount;
slippage.tokenAmount = Number(b.tokenAmount); // API returns a string
slippage.avgPriceInEthBuy = b.avgPrice;
slippage.avgPriceInEthSell = s.avgPrice;
slippage.slippage = (b.avgPrice - s.avgPrice) / b.avgPrice;
}
return slippage;
}

View File

@@ -1,38 +1,50 @@
import * as R from 'ramda';
import { Connection, ConnectionOptions, createConnection, Repository } from 'typeorm';
import { Connection, ConnectionOptions, createConnection, Repository, PromiseUtils, AdvancedConsoleLogger } from 'typeorm';
import { logUtils } from '@0x/utils';
import { EdpsExchange, EdpsSource, PriceResponse, PriceSource } from '../data_sources/slippage';
import { handleError } from '../utils';
import { string, number } from 'prop-types';
import { calculateSlippage } from '../parsers/slippage';
import { SlippageRecord } from '../entities';
import { Slippage } from '../entities';
import * as ormConfig from '../ormconfig';
// Number of orders to save at once.
const BATCH_SAVE_SIZE = 1000;
// USD amounts for slippage depths
const USD_AMOUNTS = [10, 100, 1000];
const TOKENS = ['ZRX', 'MKR', 'DAI', 'KNC', 'BNB']; // TODO: fetch from database
const USD_AMOUNTS = [10, 100, 1000, 10000];
// TODO: fetch from database
const TOKENS = ['BAT', 'DAI', 'FUN', 'MANA', 'OMG', 'REP', 'TUSD', 'ZRX', 'MKR', 'BNB', 'USDC'];
let connection: Connection;
(async () => {
connection = await createConnection(ormConfig as ConnectionOptions);
const priceSource = new PriceSource();
const edpsSource = new EdpsSource();
const resultsPerAmount = await TOKENS.map(async (symbol) => {
logUtils.log('Fetching slippage records');
let nestedSlippages: Slippage[][][] = await Promise.all(await TOKENS.map(async (symbol) => {
const usdPrice = await priceSource.getUsdPriceAsync(symbol);
USD_AMOUNTS.map(async (usdAmount) => {
return Promise.all(USD_AMOUNTS.map(async (usdAmount) => {
const amount = usdAmount / usdPrice;
console.log(amount);
const buyEdps = await edpsSource.getEdpsAsync('buy', symbol, amount);
const sellEdps = await edpsSource.getEdpsAsync('sell', symbol, amount);
for(let exchange of buyEdps.keys()) {
const slippageRecord = await calculateSlippage(usdAmount, exchange, buyEdps, sellEdps)
if (slippageRecord)
console.log(slippageRecord);
}
}
)});
//process.exit(0);
const slippages = Array.from(buyEdps.keys()).map((exchange) => {
const slippage: Slippage = calculateSlippage(usdAmount, exchange, buyEdps, sellEdps);
return slippage;
});
return slippages;
}));
}));
let slippagesWithEmptyRecords = await nestedSlippages
.reduce((acc, val) => acc.concat(val))
.reduce((acc, val) => acc.concat(val));
let slippages = slippagesWithEmptyRecords.filter((slippage) => slippage.observedTimestamp)
const SlippageRepository = connection.getRepository(Slippage);
logUtils.log(`Saving ${slippages.length} records to database`);
await SlippageRepository.save(slippages, { chunk: Math.ceil(slippages.length / BATCH_SAVE_SIZE) });
logUtils.log("Done");
process.exit(0);
})().catch(handleError);

View File

@@ -3,7 +3,7 @@ import 'mocha';
import * as R from 'ramda';
import 'reflect-metadata';
import { SlippageRecord } from '../../src/entities';
import { Slippage } from '../../src/entities';
import { createDbConnectionOnceAsync } from '../db_setup';
import { chaiSetup } from '../utils/chai_setup';
@@ -11,11 +11,14 @@ import { testSaveAndFindEntityAsync } from './util';
chaiSetup.configure();
const slippageRecord = {
time: 1234,
const slippage = {
observedTimestamp: 1549587475793,
symbol: 'ZRX',
exchange: 'Paradex',
exchange: 'Radar Relay',
usdAmount: 10,
tokenAmount: 25,
avgPriceInEthBuy: 0.0022,
avgPriceInEthSell: 0.002,
slippage: 0.01
};
@@ -23,10 +26,10 @@ const slippageRecord = {
describe('Slippage entity', () => {
it('save/find', async () => {
const connection = await createDbConnectionOnceAsync();
const slippageRecords = [slippageRecord];
const slippageRepository = connection.getRepository(SlippageRecord);
for (const record of slippageRecords) {
await testSaveAndFindEntityAsync(slippageRepository, record);
const slippages = [slippage];
const slippageRepository = connection.getRepository(Slippage);
for (const slippage of slippages) {
await testSaveAndFindEntityAsync(slippageRepository, slippage);
}
});
});