JSPM

  • Created
  • Published
  • Downloads 63
  • Score
    100M100P100Q76276F
  • License MIT

A client for fetching stock data from the Tehran Stock Exchange (TSETMC). Works in Browser, Node and as CLI.

Package Exports

  • tse-client

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (tse-client) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

TSE Client GitHub tag GitHub issues

A client for fetching stock data from the Tehran Stock Exchange (TSETMC).
Works in Browser, Node, and as CLI.
The 0.x and 1.x versions were a direct port of the official Windows app.

CLI

Install:

npm install tse-client -g

Basic:

tse ذوب
tse ذوب فولاد خساپا شپنا
tse "شاخص کل6"
tse "شاخص کل فرابورس6" "شاخص کل (هم وزن)6"

Adjust prices:

tse آپ -j 1 # افزایش سرمایه + سود نقدی
tse آپ -j 2 # افزایش سرمایه

Select columns:

tse فملی -c "6,7,8,10"
tse فملی -c "6:OPEN 7:HIGH 8:LOW 10:CLOSE"
tse فملی -c "4:date 10:close 13:count 12:volume"
tse ls -A
tse ls -D
# defaults: "4:DATE 6:OPEN 7:HIGH 8:LOW 9:LAST 10:CLOSE 12:VOL"

History depth:

tse ذوب -b 3m       # سه ماه گذشته (پیشفرض)
tse ذوب -b 40d      # چهل روز گذشته
tse ذوب -b 2y       # دو سال گذشته
tse ذوب -b 13920101 # تاریخ شمسی
tse ذوب -b 13800101 # کمترین تاریخ ممکن

File generation:

tse کگل -o /mydir # output directory
tse کگل -n 3      # file name
tse کگل -x txt    # file extension
tse کگل -e ascii  # file encoding
tse کگل -l @      # file delimiter char
tse کگل -H        # file without headers

Select symbols from file:

tse ls -F "i=34" > car.txt
tse ls -F "i=27" > iron.txt
tse -i car.txt -o ./car-group
tse -i iron.txt -o ./iron-group

Select symbols by filter:

# tse -f "t= نوع نماد i= گروه صنعت m= نوع بازار"
tse -f "i=27"                 # گروه صنعت: فلزات اساسی
tse -f "i=27 t=300"           # گروه صنعت: فلزات اساسی & نوع نماد: سهم بورس
tse -f "m=4 i=27,53,38 t=404" # نوع بازار: پایه & گروه صنعت: فلزات و سیمان و قند & نوع نماد: حق تقدم

tse ls -T
tse ls -I
tse ls -M

tse ls -F "i=27 t=300" # گروه فلزات بازار بورس
tse ls -F "i=27 t=303" # گروه فلزات بازار فرابورس
tse ls -F "i=27 t=309" # گروه فلزات بازار پایه

tse ls -F "i=34 t=300" # گروه خودرو بازار بورس
tse ls -F "i=34 t=303" # گروه خودرو بازار فرابورس
tse ls -F "i=34 t=309" # گروه خودرو بازار پایه

tse ls -F "t=68"       # شاخص های بازار بورس
tse ls -F "t=69"       # شاخص های بازار فرابورس

Save settings:

tse ذوب فولاد -o ./mytse --save
tse
tse -x txt
tse -n 3 --save
tse -o ./myother --save
tse

View saved settings and more:

tse ls -S
tse ls -D
tse ls -F "i=34"
tse ls -F "i=27 t=300"
tse ls -M -T -I
tse ls -T -O 1  # order by count (descending)
tse ls -T -O 1_ # order by count (ascending)
tse ls -h

Node

Install:

npm install tse-client

Usage:

const tse = require('tse');

(async () => {
  
  // basic
  let { error, data } = await tse.getPrices(['ذوب', 'فولاد']);
  if (!error) console.log(data);
  
  // adjusted data
  let { data } = await tse.getPrices(['خساپا'], {adjustPrices: 1});
  
  // select columns (default names)
  let { data } = await tse.getPrices(['شپنا'], {columns: [4,7,8]});
  
  // select columns (custom names)
  let { data } = await tse.getPrices(['شپنا'], {columns: [[4,'DATE'],[7,'MAX'],[8,'MIN']]});
  
  // view column info
  console.table(tse.columnList);
  
  // list of instruments
  let instruments = await tse.getInstruments();
  console.log(
    instruments.filter(i => i.YVal === '300' && i.CSecVal === '27') // گروه فلزات بازار بورس
  );
  
})();

Browser

Using standalone bundle:

(bundled with the 4 dependencies)

<script src="https://cdn.jsdelivr.net/npm/tse-client/dist/tse.bundle.min.js"></script>
<script>
  (async () => {

    // basic
    let { error, data } = await tse.getPrices(['ذوب', 'فولاد']);
    if (!error) console.log(data);
    
    // adjusted data
    let { data } = await tse.getPrices(['خساپا'], {adjustPrices: 1});
    
    // select columns (default names)
    let { data } = await tse.getPrices(['شپنا'], {columns: [4,7,8]});
    
    // select columns (custom names)
    let { data } = await tse.getPrices(['شپنا'], {columns: [[4,'DATE'],[7,'MAX'],[8,'MIN']]});
    
    // view column info
    console.table(tse.columnList);
    
    // list of instruments
    let instruments = await tse.getInstruments();
    console.log(
      instruments.filter(i => i.YVal === '300' && i.CSecVal === '27') // گروه فلزات بازار بورس
    );
    
  })();
</script>

Using the module itself:

(dependencies must be loaded before)

<script src="https://cdn.jsdelivr.net/npm/big.js"></script>
<script src="https://cdn.jsdelivr.net/npm/localforage"></script>
<script src="https://cdn.jsdelivr.net/npm/jalaali-js/dist/jalaali.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pako/dist/pako.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/tse-client/dist/tse.min.js"></script>
<script>
  tse.getPrices(['فولاد']).then(({data}) => console.log(data[0]));
</script>

Using behind a simple PHP proxy:

// proxy.php
<?php
$t  = isset($_GET['t'])  ? $_GET['t']  : '';
$a  = isset($_GET['a'])  ? $_GET['a']  : '';
$a2 = isset($_GET['a2']) ? $_GET['a2'] : '';

echo file_get_contents("http://service.tsetmc.com/tsev2/data/TseClient2.aspx?t=$t&a=$a&a2=$a2");
?>
tse.API_URL = 'http://path/to/proxy.php';
tse.getPrices(['فولاد']).then(({data}) => console.log(data[0]));

Some Info:

file desc
dist/tse.js Unminified code.
dist/tse.min.js Minified code.
dist/tse.bundle.min.js Minified dependencies + minified code.
dependency desc
big.js Required. For price adjustment calculations.
localforage Required. For storing in indexedDB.
jalaali-js Optional. Only needed for ShamsiDate column. (Recommanded to not exclude this, though you can)
pako Optional. For compression of stored data. (Highly recommanded, total data: 300 MB, compressed: 30 MB)

API

tse.API_URL

The API URL to use for HTTP requests.
Only string and valid URL.
Default: http://service.tsetmc.com/tsev2/data/TseClient2.aspx

tse.UPDATE_INTERVAL

Update data only if these many days have passed since the last update.
Only integers.
Default: 1

tse.PRICES_UPDATE_CHUNK

Amount of instruments per request.
Only integers.
Min: 1
Max: 60
Default: 50

tse.PRICES_UPDATE_CHUNK_DELAY

Amount of delay (in ms) to wait before requesting another chunk of instruments.
Default: 300

tse.PRICES_UPDATE_RETRY_COUNT

Amount of retry attempts before giving up.
Only integers.
Default: 3

tse.PRICES_UPDATE_RETRY_DELAY

Amount of delay (in ms) to wait before making another retry.
Only integers.
Default: 1000

tse.CACHE_DIR

Only in Node.
Location of the cache directory.
If the location is changed, existing content is not moved to the new location.
Default:   User's home directoy:require('os').homedir()

tse.getInstruments(struct: boolean, arr: boolean, structKey: string)

Update (if needed) and return list of instruments.

  • struct: Determine the return type for each instrument. Default true
    • true: return an Instrument object for each instrument.
    • false: return a CSV string for each instrument.
  • arr: Determine the return type. Default: true
    • true: return an array.
    • false return an Instruments object.
  • structKey: Which key of Instrument to use when struct is set to true. Default InsCode

return: Array<Instrument | string> | Instruments

Visit the official documentation for description of each Instrument field.

interface Instrument {
//                         👇 C# equivalent
  InsCode:      string; // long (int64)
  InstrumentID: string;
  LatinSymbol:  string;
  LatinName:    string;
  CompanyCode:  string;
  Symbol:       string;
  Name:         string;
  CIsin:        string;
  DEven:        string; // int (int32)
  Flow:         string; // byte
  LSoc30:       string;
  CGdSVal:      string;
  CGrValCot:    string;
  YMarNSC:      string;
  CComVal:      string;
  CSecVal:      string;
  CSoSecVal:    string;
  YVal:         string;
}

interface Instruments {
  [Instrument.InsCode]: Instrument | string;
}

tse.getPrices(symbols: string[], settings?: PriceSettings)

Update (if needed) and return prices of instruments.

  • symbols: An array of Farsi instrument symbols.
  • settings: A settings object.
    • columns: Select which ClosingPrice props to return and specify optional string for the prop.
      Default: [ [4,'date'], [6,'open'], [7,'high'], [8,'low'], [9,'last'], [10,'close'], [12,'vol'] ]
    • adjustPrices: The type of adjustment applied to returned prices.
      0: None             (بدون تعدیل)
      1: Capital Increase + Dividends   (افزایش سرمایه + سود نقدی)
      2: Capital Increase        (افزایش سرمایه)
    • startDate: Only return prices after this date. Min: '20010321'. Default: '20010321'
    • daysWithoutTrade: Whether to include days that have 0 trades. Default: false
    • csv: Geberate results as CSV strings. Default: false
    • csvHeaders: Include header row when generating CSV results. Default: true
    • csvDelimiter: A cell delimiter character to use when generating CSV results. Default: ','
    • onprogress: A callback function which gets called with a number indicating the progress. Default: undefined
    • progressTotal: A number to use as the completion point of progress. Default: 100

return: Result

interface Result {
  data:   Array<ClosingPrice>;
  error?: CustomError;
}

interface ClosingPrice {
//                              👇 C# equivalent of array item
  CompanyCode:    string[];  // string
  LatinName:      string[];  // string
  Symbol:         string[];  // string
  Name:           string[];  // string
  Date:           number[];  // int     (int32)
  ShamsiDate:     number[];  // int     (int32)
  PriceFirst:     number[];  // decimal (float128)
  PriceMax:       number[];  // decimal (float128)
  PriceMin:       number[];  // decimal (float128)
  LastPrice:      number[];  // decimal (float128)
  ClosingPrice:   number[];  // decimal (float128)
  Price:          number[];  // decimal (float128)
  Volume:         number[];  // decimal (float128)
  Count:          number[];  // decimal (float128)
  PriceYesterday: number[];  // decimal (float128)
}

interface PriceSettings {               
  columns?:          Array<[number, string?]>;
  adjustPrices?:     AdjustOption;
  daysWithoutTrade?: boolean;
  startDate?:        string;
}

interface CustomError {
  code:     ErrorType;
  title:    string;
  detail?:  string | Error;
  symbols?: string[];
  fails?:   string[];
  succs?:   string[];
}

enum AdjustOption {
  None = 0,
  CapitalIncreasePlusDividends = 1,
  CapitalIncrease = 2
}

enum ErrorType {
  FailedRequest = 1,
  IncorrectSymbol = 2,
  IncompletePriceUpdate = 3
}

Example:

const defaultSettings = {
  columns: [
    [4, 'date'],
    [6, 'open'],
    [7, 'high'],
    [8, 'low'],
    [9, 'last'],
    [10, 'close'],
    [12, 'vol']
  ],
  adjustPrices: 0,
  daysWithoutTrade: false,
  startDate: '20010321',
  csv: false,
  csvHeaders: true,
  csvDelimiter: ',',
  onprogress: undefined,
  progressTotal: 100
};

const result = await tse.getPrices(symbols=['sym1', 'sym2', ...], defaultSettings);

result.data /*
  [
    // sym1
    {
      open:  [0, 0, ...],
      high:  [0, 0, ...],
      low:   [0, 0, ...],
      last:  [0, 0, ...]
      close: [0, 0, ...],
      vol:   [0, 0, ...]
    },

    // sym2
    {
      open: [],
      high: [],
      ...
    },

    ...
  ]
*/

result.error // possible values:

undefined

{ code: 1, title: 'Failed request...',       detail: '' | Error }

{ code: 2, title: 'Incorrect Symbol',        symbols: [] }

{ code: 3, title: 'Incomplete Price Update', fails: [], succs: [] }

tse.columnList

A list of all possible columns.

index name fname
0 CompanyCode کد شرکت
1 LatinName نام لاتین
2 Symbol نماد
3 Name نام
4 Date تاریخ میلادی
5 ShamsiDate تاریخ شمسی
6 PriceFirst اولین قیمت
7 PriceMax بیشترین قیمت
8 PriceMin کمترین قیمت
9 LastPrice آخرین قیمت
10 ClosingPrice قیمت پایانی
11 Price ارزش
12 Volume حجم
13 Count تعداد معاملات
14 PriceYesterday قیمت دیروز

Some Notes

  • Instrument.Symbol characters are cleaned from zero-width characters, ك and ي.
  • The price adjustment algorithm is still a direct port of the official Windows app.
  • In Browser, the InstrumentAndShare data is stored in localStorage.
  • In Browser, the ClosingPrices data is stored in indexedDB.
  • In Node, data compression is done with the zlib module.