| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- const apiKey = document.querySelector('#api-key') as HTMLInputElement;
- {
- const storedApiKey = localStorage.getItem('fio-api-key');
- if (storedApiKey)
- apiKey.value = storedApiKey;
- }
- document.querySelector('#fetch')!.addEventListener('click', async () => {
- const loader = document.querySelector('#loader') as HTMLElement;
- loader.innerHTML = '';
- loader.style.display = 'block';
- try {
- await renderLedger(apiKey.value);
- localStorage.setItem('fio-api-key', apiKey.value);
- } catch (e) {
- console.error(e);
- }
- loader.style.display = 'none';
- });
- async function getPrices(): Promise<Record<string, number | null>> {
- const allPrices: Price[] = await fetchJSON('https://refined-prun.github.io/refined-prices/all.json');
- const priceMap: Record<string, number | null> = {};
- for (const price of allPrices)
- if (price.ExchangeCode === 'IC1')
- priceMap[price.MaterialTicker] = price.VWAP30D;
- console.log(priceMap);
- return priceMap;
- }
- const pricePromise = getPrices();
- const ledger = document.querySelector('textarea#ledger') as HTMLTextAreaElement;
- async function renderLedger(apiKey: string): Promise<void> {
- ledger.style.display = 'none';
- ledger.value = 'Time,Mat,Quantity,Actual Unit Price,Discounted Unit Price,Gateway,Debit,Credit,Contract ID\n';
- const prices = await pricePromise;
- const contracts: Contract[] = await fetchJSON('https://rest.fnar.net/contract/allcontracts',
- {headers: {'Authorization': apiKey}});
- contracts.sort((a, b) => a.DateEpochMs - b.DateEpochMs);
- for (const contract of contracts) {
- if (contract.PartnerCompanyCode === null || contract.PartnerName.endsWith(' Commodity Exchange')) continue; // NPC contract
- contract.Conditions.sort((a, b) => a.ConditionIndex - b.ConditionIndex);
- for (let i = 0; i < contract.Conditions.length; i++) {
- const condition = contract.Conditions[i];
- if ((contract.Party !== condition.Party && condition.Type === 'DELIVERY') || // counterparty is delivering
- (contract.Party === condition.Party && condition.Type === 'COMEX_PURCHASE_PICKUP')) { // we are picking up
- const time = new Date(contract.DateEpochMs).toISOString();
- const mat = condition.MaterialTicker;
- const quantity = condition.MaterialAmount;
- const totalPrice = contract.Conditions[i-1].Amount;
- ledger.value += `${time},${mat},${quantity},${prices[mat]},${totalPrice / quantity},,${totalPrice},,${contract.ContractLocalId}\n`;
- } else
- continue;
- }
- }
- ledger.style.display = 'block';
- }
- document.querySelector('#copy')!.addEventListener('click', () => {
- navigator.clipboard.writeText(ledger.value);
- });
- async function fetchJSON(url: string, options: RequestInit = {}): Promise<any> {
- const controller = new AbortController();
- const timeoutId = setTimeout(() => controller.abort(), 5000);
- const doc = await fetch(url, {...options, signal: controller.signal}).then((r) => r.json());
- clearTimeout(timeoutId);
- return doc;
- }
- interface Contract {
- Conditions: Array<ContractCondition>;
- ContractLocalId: string;
- Party: string;
- Status: string;
- PartnerName: string;
- PartnerCompanyCode: string;
- DateEpochMs: number;
- }
- interface ContractCondition {
- ConditionIndex: number;
- Type: string;
- Party: string;
- MaterialTicker: string;
- MaterialAmount: number;
- Amount: number;
- Currency: string;
- }
- interface Price {
- MaterialTicker: string
- ExchangeCode: string
- VWAP30D: number | null
- }
|