text:
import _sliceOnOccurrence from "./internal/string/_sliceOnOccurrence.js";

/**
 * Returns the string formed by the characters **before
 * the first occurrence** of the delimiter in a base string.
 * If the delimiter is not found, the function returns `undefined`.
 *
 * @category String
 *
 * @param  {string} str The base string.
 * @param  {string} delimiter The delimiter string.
 * @return {string}
 * @public
 *
 * @example
 * beforeFirst("parallelepiped", "le");
 * // => "paral"
 */
const beforeFirst = (str, delimiter) => _sliceOnOccurrence("before", "first", str, delimiter);

export default beforeFirst;


text:
/**
 * When used with `[].reduce()`, returns
 * the sum of the values in an array.
 *
 * Note that reducing arrays with non-numeric values
 * using `toSum()` can lead to unexpected results.
 * Also, note that the parentheses can be ommited.
 *
 * @category Reduce
 *
 * @return {number} The sum of the values in an array.
 * @public
 *
 * @example
 * [3, 5, 7, 9].reduce(toSum());
 * // => 24
 *
 * [3, 5, 7, 9].reduce(toSum);
 * // => 24
 */
const toSum = (...args) => {
	let func = (prevNum, nextNum) => prevNum + nextNum;
	return (args.length === 0) ? func : func(...args);
};

export default toSum;

repo_name: leofavre/canivete

repo_language: JavaScript

mime_type: text/x-java


text:
import _reactToEvent from "./internal/event/_reactToEvent.js";

/**
 * Removes one or more event listeners from one or more DOM elements at once.
 * The function is a wrapper for
 * [`Element.removeEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener)
 * that accepts a space-separated event names string and a group
 * of target DOM elements.
 *
 * @category Event
 * @param {(Window|HTMLDocument|HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements, including `document` and `window`.
 * @param {string} eventStr The event names string.
 * @param {Function} callback The function to be ignored.
 * @param {Boolean} [useCapture = false] The event phase being listened for.
 *
 * @example
 *
 * let oneElement = document.querySelector("a");
 * let manyElements = document.querySelectorAll("a");
 *
 * ignore(oneElement, "click", reactToClick, true);
 * ignore(manyElements, "click", reactToClick);
 * ignore(window, "load resize", reactToLoadAndResize);
 */
const ignore = (domEls, eventStr, callback, useCapture = false) => _reactToEvent("removeEventListener", domEls, eventStr, callback, useCapture);

export default ignore;


text:
/**
 * Delays the chaining of a promise by a specified
 * time in milliseconds.
 *
 * The function is curried so as to be used inside
 * the `.then()` method, passing along the resolved
 * value from the previous promise step to the next.
 *
 * Note that if a non-numeric parameter is passed,
 * the promise resolves without delay, skipping the
 * internal `setTimeout()`.
 *
 * @category Promise
 *
 * @param  {number} delay The delay in milliseconds.
 * @return {Promise} When fulfilled, returns the resolved value from the previous step.
 * @public
 *
 * @example
 * Promise.resolve("waiting")
 * 	.then(waitInPromise(1000))
 * 	.then(doSomethingAfterOneSecond);
 */
const waitInPromise = delay => arg =>
	(Number.isFinite(delay) && delay > 0) ?
	new Promise(resolve => setTimeout(() => resolve(arg), delay)) :
	Promise.resolve(arg);

export default waitInPromise;


text:
import _setAttrBase from "./internal/dom/_setAttrBase.js";
import _domElementsToArray from "./internal/dom/_domElementsToArray.js";

/**
 * Sets an attribute for one or more DOM elements using native
 * [`Element.setAttribute()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute).
 *
 * @category DOM
 * @param {(HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements.
 * @param {string} attrName The attribute name.
 * @param {(string|number|boolean)} value The attribute value.
 *
 * @example
 * let oneElement = createDomElement('
Level 42
');
 *
 * setAttr(oneElement, "data-level", 42);
 *
 * oneElement.getAttribute("data-level");
 * // => "42"
 *
 * oneElement.dataset.level;
 * // => "42"
 *
 * @example
 * let oneElement = createDomElement('News');
 *
 * setAttr(oneElement, "class", "button");
 *
 * oneElement.getAttribute("class");
 * // => "button"
 *
 * oneElement.className;
 * // => "button"
 *
 * @example
 * let listElement = createDomElement('

A

B

C

'),
 * 	manyElements = listElement.querySelectorAll("li");
 *
 * setAttr(manyElements, "class", "item");
 *
 * manyElements[0].className;
 * // => "item"
 *
 * manyElements[1].className;
 * // => "item"
 */
const setAttr = (domEls, attrName, value) => {
	_domElementsToArray(domEls).forEach(domEl => _setAttrBase(domEl, attrName, value));
};

export default setAttr;


text:
import _sliceOnOccurrence from "./internal/string/_sliceOnOccurrence.js";

/**
 * Returns the string formed by the characters **after
 * the last occurrence** of the delimiter in a base string.
 * If the delimiter is not found, the function returns `undefined`.
 *
 * @category String
 *
 * @param  {string} str The base string.
 * @param  {string} delimiter The delimiter string.
 * @return {string}
 * @public
 *
 * @example
 * afterLast("parallelepiped", "le");
 * // => "piped"
 */
const afterLast = (str, delimiter) => _sliceOnOccurrence("after", "last", str, delimiter);

export default afterLast;


text:
import _sliceOnOccurrence from "./internal/string/_sliceOnOccurrence.js";

/**
 * Returns the string formed by the characters **before
 * the last occurrence** of the delimiter in a base string.
 * If the delimiter is not found, the function returns `undefined`.
 *
 * @category String
 *
 * @param  {string} str The base string.
 * @param  {string} delimiter The delimiter string.
 * @return {string}
 * @public
 *
 * @example
 * beforeLast("parallelepiped", "le");
 * // => "paralle"
 */
const beforeLast = (str, delimiter) => _sliceOnOccurrence("before", "last", str, delimiter);

export default beforeLast;


text:
import _isString from "./internal/helpers/_isString.js";
import _isElementOrDocumentOrWindow from "./internal/dom/_isElementOrDocumentOrWindow.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * Triggers a custom DOM event.
 *
 * @category Event
 * @param  {(Window|HTMLDocument|HTMLElement)} domEl The DOM element, including `document` and `window`.
 * @param  {string} evtName The event name.
 * @param  {boolean} [bubbles = false] Whether the event bubbles.
 * @param  {boolean} [cancelable = false] Whether the event can be canceled.
 * @param  {*} [detail] Any information passed along.
 *
 * @example
 * let popupButton = document.querySelector(".popup__button"),
 * 	popupLayer = document.querySelector(".popup__layer");
 *
 * popupButton.addEventListener("click", evt => {
 * 	trigger(popupLayer, "open");
 * });
 */
const trigger = (domEl, evtName, bubbles = false, cancelable = false, detail = undefined) => {
	_throwErrorIf(!_isElementOrDocumentOrWindow(domEl), "An HTMLElement, including document or window, is expected as first parameter.");
	_throwErrorIf(!_isString(evtName), "A string is expected as second parameter.");

	let evt;

	if (window.CustomEvent != null) {
		evt = document.createEvent("CustomEvent");
		evt.initCustomEvent(evtName, bubbles, cancelable, detail);
	}
	else {
		evt = new CustomEvent(evtName, {
			bubbles,
			cancelable,
			detail
		});
	}

	domEl.dispatchEvent(evt);
};

export default trigger;


text:
import _simpleAt from "./internal/helpers/_simpleAt.js";

/**
 * When used with `[].reduce()`, returns
 * the object in an array in which a specific property,
 * passed as parameter, has the closest value to another,
 * also passed as parameter.
 *
 * If two or more results are found, the first one
 * is returned.
 *
 * Note that the function expects the reduced array to be
 * formed by objects with the same set of properties.
 *
 * @category Reduce
 *
 * @param {string} path The path to the property of an object.
 * @param {string} num The base value.
 * @return {Object} The object in which an specific property has the closest value to the base value.
 * @public
 *
 * @example
 * let cities = [{
 * 	"city": "Rio de Janeiro",
 * 	"temperature": 96,
 * 	"demographics": {
 * 		"population": 6.32
 * 	}
 * }, {
 * 	"city": "São Paulo",
 * 	"temperature": 82.5,
 * 	"demographics": {
 * 		"population": 12.04
 * 	}
 * }, {
 * 	"city": "Curitiba",
 * 	"temperature": 70,
 * 	"demographics": {
 * 		"population": 1.752
 * 	}
 * }, {
 * 	"city": "Florianópolis",
 * 	"temperature": 86,
 * 	"demographics": {
 * 		"population": 0.249
 * 	}
 * }];
 *
 * cities.reduce(toClosestProp("temperature", 75));
 * // => { "city": "Curitiba", [...] }
 *
 * cities.reduce(toClosestProp("demographics.population", 5));
 * // => { "city": "Rio de Janeiro", [...] }
 */
const toClosestProp = (path, num) => (prevObj, nextObj, index, arr) => {
	if (Math.abs(_simpleAt(prevObj, path) - num) <= Math.abs(_simpleAt(nextObj, path) - num)) {
		return prevObj;
	}

	return nextObj;
};

export default toClosestProp;


text:
/**
 * When used with `[].reduce()`, returns
 * the closest value to the one passed as parameter.
 *
 * If two or more results are found, the first one
 * is returned.
 *
 * Note that reducing arrays with non-numeric values
 * using `toClosest()` can lead to unexpected results.
 *
 * @category Reduce
 *
 * @param {number} num The base value.
 * @return {number} The value, from an array, closest to the base value.
 * @public
 *
 * @example
 * [3, 5, 7, 9].reduce(toClosest(6));
 * // => 5
 *
 * [3, 5, 7, 9].reduce(toClosest(-2));
 * // => 3
 */
const toClosest = num => (prevNum, nextNum) => {
	if (Math.abs(prevNum - num) <= Math.abs(nextNum - num)) {
		return prevNum;
	}
	else {
		return nextNum;
	}
};

export default toClosest;


text:
import _isString from "./internal/helpers/_isString.js";
import _isElementOrDocumentOrWindow from "./internal/dom/_isElementOrDocumentOrWindow.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * Transforms a DOM event into a promise.
 *
 * The functions takes as parameters: a DOM element,
 * the name of the event to be listened for
 * and a function that verifies if the event has already
 * happened, which receives the DOM element as parameter.
 *
 * Like all promises in Javascript, the function will
 * only fulfill once, either if the verification function
 * returns true or when the event occurs for the first time.
 *
 * Note that the function throws an error if the first two
 * parameters are not a DOM element and a string.
 *
 * @category Promise
 *
 * @param  {(Window|HTMLDocument|HTMLElement)} domEl The DOM element, including `document` and `window`.
 * @param  {string} evtName The event to be listened for.
 * @param  {function} [happened = domEl => false] The verification function.
 * @return {Promise} When fulfilled, returns the DOM element.
 *
 * @example
 * let checkbox = document.createElement("input");
 * checkbox.type = "checkbox";
 * document.body.appendChild(checkbox);
 *
 * eventAsPromise(checkbox, "change")
 * 	.then(doSomethingAfterChange);
 *
 * @example
 * let imageEl = document.createElement("img");
 * imageEl.src = "img.jpg";
 * document.body.appendChild(imageEl);
 *
 * eventAsPromise(imageEl, "load", imageEl => imageEl.complete)
 * 	.then(doSomethingAfterImageLoaded);
 */
const eventAsPromise = (domEl, evtName, happened = domEl => false) => {
	_throwErrorIf(!_isElementOrDocumentOrWindow(domEl), "An HTMLElement, document or window are expected as first parameter.");
	_throwErrorIf(!_isString(evtName), "A string is expected as second parameter.");

	return new Promise(resolve => {
		const dealWithEvent = evt => {
			domEl.removeEventListener(evtName, dealWithEvent, true);
			resolve(domEl);
		};

		if (happened(domEl)) {
			resolve(domEl);
		}
		else {
			domEl.addEventListener(evtName, dealWithEvent, true);
		}
	});
};

export default eventAsPromise;


text:
/**
 * When used with `[].reduce()`, returns
 * the average of the values in an array.
 *
 * Note that reducing arrays with non-numeric values
 * using `toAverage()` can lead to unexpected results.
 * Also, note that the parentheses can be ommited.
 *
 * @category Reduce
 *
 * @return {number} The average of the values in an array.
 * @public
 *
 * @example
 * [3, 5, 7, 9].reduce(toAverage());
 * // => 6
 *
 * [3, 5, 7, 9].reduce(toAverage);
 * // => 6
 */
const toAverage = (...args) => {
	let func = (prevNum, nextNum, index, arr) => {
		let isLastIteration = (index === arr.length - 1);
		return (!isLastIteration) ? (prevNum + nextNum) : (prevNum + nextNum) / arr.length;
	};

	return (args.length === 0) ? func : func(...args);
};

export default toAverage;


text:
import _validateModifyBemClassArgs from "./internal/bem/_validateModifyBemClassArgs.js";
import _parseBem from "./internal/bem/_parseBem.js";

/**
 * Modifies the CSS classes from a DOM element according
 * to the [BEM methodology](https://en.bem.info/methodology/).
 * Unlike [`modifyBemClass()`](#modifybemclass), it ommits the original block
 * or element CSS class if a modified version is output.
 *
 * @category BEM
 *
 * @param  {HTMLElement} domEl The DOM element.
 * @param  {BemObject} bemObj The object describing BEM class changes (see table below).
 * @param  {Array} delimiters The BEM delimiters.
 *
 * @example
 * let domEl = document.createElement("div"),
 * 	delimiters = ["__", "--", "-"];
 *
 * modifyBemClassCompact(domEl, {
 * 	"swiper": {
 * 		"slides": 5,
 * 		"current": 2,
 * 		"playing": true
 * 	}
 * }, delimiters);
 *
 * domEl.className;
 * // => "swiper--slides-5 swiper--current-2 swiper--playing"
 *
 * modifyBemClassCompact(domEl, {
 * 	"swiper": {
 * 		"current": 3,
 * 		"playing": false
 * 	}
 * }, delimiters);
 *
 * domEl.className;
 * // => "swiper--slides-5 swiper--current-3"
 */
const modifyBemClassCompact = (domEl, bemObj, delimiters) => {
	_validateModifyBemClassArgs(domEl, bemObj, delimiters);
	return _parseBem(bemObj, domEl, delimiters, false);
};

export default modifyBemClassCompact;


text:
import _simpleAt from "./internal/helpers/_simpleAt.js";
import _simpleSet from "./internal/helpers/_simpleSet.js";

/**
 * Groups the contents of an array by one or more iteratees.
 * This function is similar to Lodash
 * [`groupBy()`](https://lodash.com/docs/4.17.4#groupBy),
 * except it can create nested groups but cannot receive
 * strings for iteratees.
 *
 * @category Collection
 *
 * @param  {Array} collection The original array.
 * @param  {...Function} [...iteratees] The functions used to group the array of objects by their results.
 * @return {Object} The resulting object.
 *
 * @example
 *
 * const getLength = str => str.length;
 * const getFirstLetter = str => str.slice(0, 1);
 *
 * deepGroupBy(["one", "two", "three"], getLength, getFirstLetter);
 * // => {
 * // => 	"3": {"o": ["one"], "t": ["two"]},
 * // => 	"5": {"t": ["three"]}
 * // => }
 *
 * @example
 *
 * const getLength = str => str.length;
 * const getFirstLetter = str => str.slice(0, 1);
 *
 * deepGroupBy(["one", "two", "three"], getFirstLetter, getLength);
 * // => {
 * // => 	"o": {"3": ["one"]},
 * // => 	"t": {"3": ["two"], "5": ["three"]}
 * // => }
 *
 * @example
 *
 * const stores = [{
 * 	"name": "Iguatemi",
 * 	"city": "Campinas",
 * 	"state": "SP"
 * }, {
 * 	"name": "Jardins",
 * 	"city": "São Paulo",
 * 	"state": "SP"
 * }, {
 * 	"name": "Iguatemi",
 * 	"city": "São Paulo",
 * 	"state": "SP"
 * }, {
 * 	"name": "Pedras",
 * 	"city": "Búzios",
 * 	"state": "RJ"
 * }, {
 * 	"name": "Ipanema",
 * 	"city": "Rio de Janeiro",
 * 	"state": "RJ"
 * }, {
 * 	"name": "Leblon",
 * 	"city": "Rio de Janeiro",
 * 	"state": "RJ"
 * }, {
 * 	"name": "ParkShopping",
 * 	"city": "Brasília",
 * 	"state": "DF"
 * }];
 *
 * const getStateName = item => item.state;
 * const getCityName = item => item.city;
 *
 * deepGroupBy(stores, getStateName, getCityName);
 * // => {
 * // => 	"SP": { "Campinas": [...], "São Paulo": [...] },
 * // => 	"RJ": { "Búzios": [...], "Rio de Janeiro": [...] },
 * // => 	"DF": { "Brasília": [...] }
 * // => }
 */
const deepGroupBy = (collection, ...iteratees) => {
	let paths = collection.map(value => iteratees.map(iteratee => iteratee(value))),
		result = {};

	paths.forEach((path, index) => {
		let currentValue = _simpleAt(result, path) || [],
			newValue = currentValue.concat([collection[index]]);

		_simpleSet(result, path, newValue);
	});

	return result;
};

export default deepGroupBy;


text:
import _validateModifyBemClassArgs from "./internal/bem/_validateModifyBemClassArgs.js";
import _parseBem from "./internal/bem/_parseBem.js";

/**
 * @typedef {Object} BemObject
 * @property {Object} name An object which key is a BEM block or element, e.g. `menu` or `landing__area`.
 * @property {Object} name.modifier An object representing a modifiers and their values, e.g. `{active: false}` or `{level: 42}`.
 */

/**
 * Modifies the CSS classes from a DOM element according
 * to the [BEM methodology](https://en.bem.info/methodology/).
 *
 * @category BEM
 *
 * @param  {HTMLElement} domEl The DOM element.
 * @param  {BemObject} bemObj The object describing BEM class changes (see table below).
 * @param  {Array} delimiters The BEM delimiters.
 *
 * @example
 * let domEl = document.createElement("div"),
 * 	delimiters = ["__", "--", "-"];
 *
 * modifyBemClass(domEl, {
 * 	"swiper": {
 * 		"slides": 5,
 * 		"current": 2,
 * 		"playing": true
 * 	}
 * }, delimiters);
 *
 * domEl.className;
 * // => "swiper swiper--slides-5 swiper--current-2 swiper--playing"
 *
 * modifyBemClass(domEl, {
 * 	"swiper": {
 * 		"current": 3,
 * 		"playing": false
 * 	}
 * }, delimiters);
 *
 * domEl.className;
 * // => "swiper swiper--slides-5 swiper--current-3"
 */
const modifyBemClass = (domEl, bemObj, delimiters) => {
	_validateModifyBemClassArgs(domEl, bemObj, delimiters);
	return _parseBem(bemObj, domEl, delimiters, true);
};

export default modifyBemClass;


text:
import _defaultComparator from "./internal/sort/_defaultComparator.js";

/**
 * When used with `[].sort()`, sorts
 * the array in ascending alphabetical order.
 *
 * Note that the parentheses can be ommited.
 *
 * @category Sort
 *
 * @return {Array} The array in ascending alphabetical order.
 *
 * @example
 * let musqueteers = ["Athos", "Porthos", "Aramis"];
 *
 * musqueteers.sort(byAlphabeticalOrder());
 * // => ["Aramis", "Athos", "Porthos"]
 *
 * musqueteers.sort(byAlphabeticalOrder);
 * // => ["Aramis", "Athos", "Porthos"]
 */
const byAlphabeticalOrder = (...args) =>
	(args.length === 0) ? _defaultComparator : _defaultComparator(...args);

export default byAlphabeticalOrder;


text:
import toSum from "./toSum.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * Calculates and returns the distance between two points,
 * given their cartesian coordinates, represented, each one,
 * by an array of numbers.
 *
 * For example, the point in a plane A(x, y) should be passed
 * to the function as `[x, y]`. Likewise, the point in
 * 3D space A(x, y, z) should be passed as `[x, y, z]`.
 *
 * The function deals with cartesian coordinates in
 * [n-dimensional spaces](https://en.wikipedia.org/wiki/Euclidean_distance#n_dimensions).
 *
 * @category Geometry
 * @param {Array.<number>} coordA An array representing a cartesian coordinate.
 * @param {Array.<number>} coordB An array representing a cartesian coordinate.
 * @return {number} The distance between the two cartesian coordinates.
 *
 * @example
 * getDistanceBetweenCoords([0, 0], [3, 4]);
 * // => 5
 *
 * getDistanceBetweenCoords([2, 1], [5, 5]);
 * // => 5
 *
 * getDistanceBetweenCoords([2, 1, 8], [5, 5, 0]);
 * // => 9.433981132056603
 *
 * getDistanceBetweenCoords([2], [5]);
 * // => 3
 */
const getDistanceBetweenCoords = (coordA, coordB) => {
	let areParamsValid = [coordA, coordB]
		.every(coord => Array.isArray(coord) &&
			coord.every(Number.isFinite) &&
			coord.length === coordA.length);

	_throwErrorIf(!areParamsValid, "Two arrays of numbers with the same length, representing cartesian coordinates, are expected as parameters.");

	return Math.sqrt(coordA
		.map((coord, index) => Math.pow(coord - coordB[index], 2))
		.reduce(toSum));
};

export default getDistanceBetweenCoords;


text:
import _changeClassWithMethod from "./internal/classname/_changeClassWithMethod.js";
import _domElementsToArray from "./internal/dom/_domElementsToArray.js";

/**
 * Adds a CSS class to one or more DOM elements.
 *
 * @category ClassName
 *
 * @param  {(HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements.
 * @param  {string} className The CSS class name.
 *
 * @example
 * let oneElement = document.querySelector("a");
 * addClass(oneElement, "link");
 *
 * oneElement.className;
 * // => "link"
 *
 * @example
 * let manyElements = document.querySelectorAll("a");
 * addClass(manyElements, "link");
 *
 * manyElements[0].className;
 * // => "link"
 */
const addClass = (domEls, className) => {
	_domElementsToArray(domEls).forEach(domEl => _changeClassWithMethod(domEl, className, "add"));
};

export default addClass;


text:
/**
 * Returns the time passed since a timestamp, in milliseconds;
 *
 * @category Time
 * @param  {number} timestamp The time stamp.
 * @return {number} Time passed since the timestamp, in milliseconds.
 *
 * @example
 * let timestamp = +new Date(),
 * 	result = 0;
 *
 * setTimeout(() => {
 * 	result = timeSince(timestamp);
 * }, 150);
 *
 * result;
 * // => 150
 * // This value is approximate and may vary.
 */
const timeSince = timestamp => {
	return Number.isFinite(timestamp) ? ((+new Date()) - timestamp) : undefined;
};

export default timeSince;


text:
import _isBooleanAttribute from "./internal/dom/_isBooleanAttribute.js";

/**
 * Gets a DOM element attribute using native
 * [`Element.getAttribute()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute),
 * except that the presence of an attribute without
 * a value will return `true` instead of an empty string,
 * and the absence will return `false`. The function also
 * deals with boolean values using old HTML4 syntax,
 * like `<option selected="selected">`.
 *
 * @category DOM
 *
 * @param  {HTMLElement} domEl The DOM element.
 * @param  {string} attrName The attribute name.
 * @return {(string|Boolean)} The attribute value.
 *
 * @example
 * // HTML5 syntax
 * let inputElement = createDomElement('<input type="checkbox" checked>');
 *
 * getAttr(inputElement, "checked");
 * // => true
 *
 * @example
 * // HTML4 syntax
 * let inputElement = createDomElement('<input type="checkbox" checked="checked"/>');
 *
 * getAttr(inputElement, "checked");
 * // => true
 *
 * @example
 * let videoElement = createDomElement('<video src="video.mp4" controls>');
 *
 * getAttr(videoElement, "src");
 * // => "video.mp4"
 *
 * getAttr(videoElement, "controls");
 * // => true
 *
 * getAttr(videoElement, "muted");
 * // => false
 */
const getAttr = (domEl, attrName) => {
	let value = domEl.getAttribute(attrName);

	if (_isBooleanAttribute(attrName) && attrName === value) {
		value = true;
	}

	value = (value === "") ? true : (value == null) ? false : value;
	return value;
};

export default getAttr;


text:
import _isElement from "./internal/helpers/_isElement.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * Verifies if a DOM element has a CSS class.
 *
 * @category ClassName
 *
 * @param  {HTMLElement} domEl The DOM element.
 * @param  {string} className The CSS class name.
 * @return {boolean} Whether the element has the CSS class name.
 *
 * @example
 * let oneElement = document.querySelector("a");
 * oneElement.className = "link reference";
 *
 * hasClass(oneElement, "link");
 * // => true
 *
 * hasClass(oneElement, "button");
 * // => false
 */
const hasClass = (domEl, className) => {
	_throwErrorIf(!_isElement(domEl), "An HTMLElement is expected as parameter.");
	return domEl.classList.contains(className);
};

export default hasClass;


text:
import _setAttrBase from "./internal/dom/_setAttrBase.js";
import _domElementsToArray from "./internal/dom/_domElementsToArray.js";

/**
 * Removes an attribute from one or more DOM elements using native
 * [`Element.removeAttribute()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute).
 *
 * @category DOM
 * @param {(HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements.
 * @param {string} attrName The attribute name.
 *
 * @example
 * let oneElement = createDomElement('
Level 42
');
 *
 * removeAttr(oneElement, "data-level");
 *
 * oneElement.getAttribute("data-level");
 * // => null
 *
 * oneElement.dataset.level;
 * // => undefined
 *
 * @example
 * let oneElement = createDomElement('News');
 *
 * removeAttr(oneElement, "class");
 *
 * oneElement.getAttribute("class");
 * // => null
 *
 * oneElement.className;
 * // => ""
 *
 * @example
 * let listHtml = '

A

B

';
 * 	listElement = createDomElement(listElement),
 * 	manyElements = listElement.querySelectorAll("li");
 *
 * removeAttr(manyElements, "class");
 *
 * manyElements[0].className;
 * // => ""
 *
 * manyElements[1].className;
 * // => ""
 */
const removeAttr = (domEls, attrName) => {
	_domElementsToArray(domEls).forEach(domEl => _setAttrBase(domEl, attrName, false));
};

export default removeAttr;


text:
import toAverage from "./toAverage.js";
import _simpleAt from "./internal/helpers/_simpleAt.js";

/**
 * When used with `[].reduce()`, returns
 * the object in an array in which a specific property,
 * passed as parameter, has the closest value to the average.
 *
 * If two or more results are found, the first one
 * is returned.
 *
 * Note that the function expects the reduced array to be
 * formed by objects with the same set of properties.
 *
 * @category Reduce
 *
 * @param {string} path The path to the property of an object.
 * @return {Object} The object in which an specific property has the closest value to the average.
 * @public
 *
 * @example
 * let cities = [{
 * 	"city": "Rio de Janeiro",
 * 	"temperature": 96,
 * 	"demographics": {
 * 		"population": 6.32
 * 	}
 * }, {
 * 	"city": "São Paulo",
 * 	"temperature": 82.5,
 * 	"demographics": {
 * 		"population": 12.04
 * 	}
 * }, {
 * 	"city": "Curitiba",
 * 	"temperature": 70,
 * 	"demographics": {
 * 		"population": 1.752
 * 	}
 * }, {
 * 	"city": "Florianópolis",
 * 	"temperature": 86,
 * 	"demographics": {
 * 		"population": 0.249
 * 	}
 * }];
 *
 * // average "temperature": 83.625
 * // average "population": 5.09025
 *
 * cities.reduce(toAverageProp("temperature"));
 * // => { "city": "São Paulo", [...] }
 *
 * cities.reduce(toAverageProp("demographics.population"));
 * // => { "city": "Rio de Janeiro", [...] }
 */
const toAverageProp = path => {
	let average;

	return (prevObj, nextObj, index, arr) => {
		average = average || arr.map(obj => _simpleAt(obj, path)).reduce(toAverage());

		if (Math.abs(_simpleAt(prevObj, path) - average) <= Math.abs(_simpleAt(nextObj, path) - average)) {
			return prevObj;
		}
		else {
			return nextObj;
		}
	};
};

export default toAverageProp;


text:
import _recursiveSort from "./internal/sort/_recursiveSort.js";
import _parseSortFields from "./internal/sort/_parseSortFields.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * @typedef {Object} SortField
 * @property {string} path The path to the property of an object.
 * @property {Function} [primer] The function used to process each value before sorting.
 * @property {boolean} [reverse] Whether the result should be reversed.
 */

/**
 * When used with `[].sort()`, returns an array of
 * objects sorted by one or more criteria, passed as
 * parameters.
 *
 * Each parameter can be eitheir a path to an object
 * property, passed as a string, or an object containing
 * a path to an object property, a boolean value indicating
 * if the result should be reversed, and a function to
 * process each value before sorting.
 *
 * @category Sort
 *
 * @param  {...(string|SortField)} ...fields The criteria used to sort the array of objects.
 * @return {Array.<Object>} The resulting array.
 *
 * @example
 * let places = [{
 * 	"name": "Ipanema",
 * 	"location": {
 * 		"city": "Rio de Janeiro",
 * 		"state": "RJ"
 * 	}
 * }, {
 * 	"name": "Pedras",
 * 	"location": {
 * 		"city": "Búzios",
 * 		"state": "RJ"
 * 	}
 * }, {
 * 	"name": "Morumbi",
 * 	"location": {
 * 		"city": "São Paulo",
 * 		"state": "SP"
 * 	}
 * }];
 *
 * places.sort(byProps("name"));
 * // Sorts places by name
 * // => [
 * // =>	{ "name": "Ipanema", [...] },
 * // =>	{ "name": "Morumbi", [...] },
 * // =>	{ "name": "Pedras", [...] }
 * // => ]
 *
 * places.sort(byProps({ "path": "name", "reverse": true });
 * // Sorts places by name in reversed order
 * // => [
 * // =>	{ "name": "Pedras", [...] },
 * // =>	{ "name": "Morumbi", [...] },
 * // =>	{ "name": "Ipanema", [...] }
 * // => ]
 *
 * places.sort(byProps("location.state", "location.city", "name"));
 * // Sorts places by state, city and name
 * // => [
 * // =>	{ "name": "Pedras", [...] },
 * // =>	{ "name": "Ipanema", [...] },
 * // =>	{ "name": "Morumbi", [...] }
 * // => ]
 *
 * places.sort(byProps({ "path": "location.state", "reverse": true }, "location.city", "name"));
 * // Sorts places by state (in reversed order), city and name
 * // => [
 * // =>	{ "name": "Morumbi", [...] },
 * // =>	{ "name": "Pedras", [...] },
 * // =>	{ "name": "Ipanema", [...] }
 * // => ]
 *
 * @example
 * let numbers = [{
 * 	"value": 35
 * }, {
 * 	"value": -20
 * }, {
 * 	"value": 3
 * }, {
 * 	"value": 0.8
 * }];
 *
 * numbers.sort(byProps("value"));
 * // Sorts numbers by value in ascending order
 * // => [{ "value": -20 }, { "value": 0.8 }, { "value": 3 }, { "value": 35 }]
 *
 * numbers.sort(byProps({ "path": "value", "primer": Math.abs }));
 * // Sorts numbers by value in ascending order but ignoring the minus sign
 * // => [{ "value": 0.8 }, { "value": 3 }, { "value": -20 }, { "value": 35 }]
 */
const byProps = (...fields) => {
	_throwErrorIf(fields.length === 0, "One or more sort criterias should be passed as parameters.");
	return _recursiveSort(_parseSortFields(fields));
};

export default byProps;


text:
import _simpleAt from "./internal/helpers/_simpleAt.js";

/**
 * When used with `[].reduce()`, returns
 * the object in an array in which a specific property
 * has the largest value.
 *
 * If two or more results are found, the first one
 * is returned.
 *
 * Note that the function expects the reduced array to be
 * formed by objects with the same set of properties.
 *
 * @category Reduce
 *
 * @param {string} path The path to the property of an object.
 * @return {Object} The object in which a specific property has the largest value.
 * @public
 *
 * @example
 * let cities = [{
 * 	"city": "Rio de Janeiro",
 * 	"temperature": 96,
 * 	"demographics": {
 * 		"population": 6.32
 * 	}
 * }, {
 * 	"city": "São Paulo",
 * 	"temperature": 82.5,
 * 	"demographics": {
 * 		"population": 12.04
 * 	}
 * }, {
 * 	"city": "Curitiba",
 * 	"temperature": 70,
 * 	"demographics": {
 * 		"population": 1.752
 * 	}
 * }, {
 * 	"city": "Florianópolis",
 * 	"temperature": 86,
 * 	"demographics": {
 * 		"population": 0.249
 * 	}
 * }];
 *
 * cities.reduce(toLargestProp("temperature"));
 * // => { "city": "Rio de Janeiro", [...] }
 *
 * cities.reduce(toLargestProp("demographics.population"));
 * // => { "city": "São Paulo", [...] }
 */
const toLargestProp = path => (prevObj, nextObj) => {
	if (_simpleAt(prevObj, path) >= _simpleAt(nextObj, path)) {
		return prevObj;
	}

	return nextObj;
};

export default toLargestProp;


text:
import _changeClassWithMethod from "./internal/classname/_changeClassWithMethod.js";
import _domElementsToArray from "./internal/dom/_domElementsToArray.js";

/**
 * Removes a CSS class from one or more DOM elements.
 *
 * @category ClassName
 *
 * @param  {(HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements.
 * @param  {string} className The CSS class name.
 *
 * @example
 * let oneElement = document.querySelector(".link.base");
 * removeClass(oneElement, "link");
 *
 * oneElement.className;
 * // => "base"
 *
 * @example
 * let manyElements = document.querySelectorAll(".link.base");
 * removeClass(manyElements, "link");
 *
 * manyElements[0].className;
 * // => "base"
 */
const removeClass = (domEls, className) => {
	_domElementsToArray(domEls).forEach(domEl => _changeClassWithMethod(domEl, className, "remove"));
};

export default removeClass;


text:
import parents from "./parents.js";
import _isElementOrDocumentOrWindow from "./internal/dom/_isElementOrDocumentOrWindow.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * The same as [`parents()`](#parents), except it includes
 * the DOM element itself.
 *
 * @category DOM
 * @param  {HTMLElement} domEl The DOM element.
 * @return {Array.<HTMLElement>} The DOM element and its parents.
 *
 * @example
 * let domChild = document.createElement("div"),
 * 	domParent = document.createElement("div"),
 * 	domGrandparent = document.createElement("div"),
 * 	body = document.body,
 * 	html = document.querySelector("html");
 *
 * domParent.appendChild(domChild);
 * domGrandparent.appendChild(domParent);
 * body.appendChild(domGrandparent);
 *
 * selfAndParents(domChild);
 * // => [domChild, domParent, domGrandparent, body, html, document]
 */
const selfAndParents = domEl => {
	_throwErrorIf(!_isElementOrDocumentOrWindow(domEl), "An HTMLElement is expected as parameter.");
	return [domEl].concat(parents(domEl));
};

export default selfAndParents;


text:
import _formatBemRadical from "./internal/bem/_formatBemRadical.js";
import _formatBemModifier from "./internal/bem/_formatBemModifier.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * Formats a CSS class according to the
 * [BEM methodology](https://en.bem.info/methodology/).
 * The function receives a block, an element, a modifier, a value
 * for the modifier and an array of BEM delimiters, e.g. `__`,
 * `--` and `-`.
 *
 * @category BEM
 *
 * @param  {string} block The BEM block.
 * @param  {string} [element] The BEM element.
 * @param  {string} [modifier] The BEM modifier.
 * @param  {(string|number|boolean)} [value = true] The BEM modifier value.
 * @param  {Array.<string>} delimiters The BEM delimiters.
 * @return {string} The BEM CSS class.
 *
 * @example
 * let delimiters = ["__", "--", "-"];
 *
 * formatBemClass("menu", delimiters);
 * // => "menu"
 *
 * formatBemClass("menu", "item", delimiters);
 * // => "menu__item"
 *
 * formatBemClass("menu", "item", "active", delimiters);
 * // => "menu__item--active"
 *
 * formatBemClass("menu", "item", "active", false, delimiters);
 * // => "menu__item"
 *
 * formatBemClass("menu", "item", "active", true, delimiters);
 * // => "menu__item--active"
 *
 * formatBemClass("menu", "item", "level", 42, delimiters);
 * // => "menu__item--level-42"
 *
 * formatBemClass("menu", "item", "level", "42", delimiters);
 * // => "menu__item--level-42"
 *
 * @example
 * let delimiters = ["__", "--", "-"];
 *
 * formatBemClass("button", null, "active", delimiters);
 * // => "button--active"
 *
 * formatBemClass("button", null, "active", false, delimiters);
 * // => "button"
 *
 * formatBemClass("button", null, "active", true, delimiters);
 * // => "button--active"
 *
 * formatBemClass("button", null, "level", 42, delimiters);
 * // => "button--level-42"
 *
 * formatBemClass("button", null, "level", "42", delimiters);
 * // => "button--level-42"
 */
const formatBemClass = (...args) => {
	let block = args[0] || "";
	let delimiters = args[args.length - 1];

	_throwErrorIf((args.length < 2), "At least a string representing a BEM block and an array representing BEM delimiters should be passed as parameters.");

	let element,
		modifier,
		value = true;

	if (args.length > 2) {
		element = args[1];
	}

	if (args.length > 3) {
		modifier = args[2];
	}

	if (args.length > 4) {
		value = args[3];
	}

	let radical = _formatBemRadical(block, element, delimiters);
	let classModifier = _formatBemModifier(modifier, value, delimiters);

	return `${radical}${classModifier}`;
};

export default formatBemClass;


text:
import _simpleAt from "./internal/helpers/_simpleAt.js";

/**
 * When used with `[].reduce()`, returns
 * the object in an array in which a specific property
 * has the smallest property.
 *
 * If two or more results are found, the first one
 * is returned.
 *
 * Note that the function expects the reduced array to be
 * formed by objects with the same set of properties.
 *
 * @category Reduce
 *
 * @param {string} path The path to the property of an object.
 * @return {Object} The object in which a specific property has the smallest value.
 * @public
 *
 * @example
 * let cities = [{
 * 	"city": "Rio de Janeiro",
 * 	"temperature": 96,
 * 	"demographics": {
 * 		"population": 6.32
 * 	}
 * }, {
 * 	"city": "São Paulo",
 * 	"temperature": 82.5,
 * 	"demographics": {
 * 		"population": 12.04
 * 	}
 * }, {
 * 	"city": "Curitiba",
 * 	"temperature": 70,
 * 	"demographics": {
 * 		"population": 1.752
 * 	}
 * }, {
 * 	"city": "Florianópolis",
 * 	"temperature": 86,
 * 	"demographics": {
 * 		"population": 0.249
 * 	}
 * }];
 *
 * cities.reduce(toSmallestProp("temperature"));
 * // => { "city": "Curitiba", [...] }
 *
 * cities.reduce(toSmallestProp("demographics.population"));
 * // => { "city": "Florianópolis", [...] }
 */
const toSmallestProp = path => (prevObj, nextObj) => {
	if (_simpleAt(nextObj, path) >= _simpleAt(prevObj, path)) {
		return prevObj;
	}

	return nextObj;
};

export default toSmallestProp;


text:
import _isElementOrDocumentOrWindow from "./internal/dom/_isElementOrDocumentOrWindow.js";
import _throwErrorIf from "./internal/validation/_throwErrorIf.js";

/**
 * Returns all parents of a DOM element,
 * from the closest to the most distant.
 *
 * @category DOM
 * @param  {HTMLElement} domEl The DOM element.
 * @return {Array.<HTMLElement>} The DOM element parents.
 *
 * @example
 * let domChild = document.createElement("div"),
 * 	domParent = document.createElement("div"),
 * 	domGrandparent = document.createElement("div"),
 * 	body = document.body,
 * 	html = document.querySelector("html");
 *
 * domParent.appendChild(domChild);
 * domGrandparent.appendChild(domParent);
 * body.appendChild(domGrandparent);
 *
 * parents(domChild);
 * // => [domParent, domGrandparent, body, html, document]
 */
const parents = (domEl, memo = []) => {
	if (memo.length === 0) {
		_throwErrorIf(!_isElementOrDocumentOrWindow(domEl), "An HTMLElement is expected as parameter.");
	}

	let parentNode = domEl.parentNode;
	return (!parentNode) ? memo : parents(parentNode, memo.concat([parentNode]));
};

export default parents;


text:
import setAttr from "./setAttr.js";

/**
 * The same as [`setAttr()`](#setattr), except it takes an object
 * with attribute name and value pairs to set one or
 * many attributes at once.
 *
 * @category DOM
 * @param {(HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements.
 * @param {Object} attrObj The object with attribute name and value pairs, e.g. `{ "data-level": 42 }`.
 *
 * @example
 * let oneElement = createDomElement('
Level 42
');
 *
 * setAttrs(oneElement, {
 * 	"data-level": 42,
 * 	"class": "level"
 * });
 *
 * oneElement.getAttribute("data-level");
 * // => "42"
 *
 * oneElement.dataset.level;
 * // => "42"
 *
 * oneElement.getAttribute("class");
 * // => "level"
 *
 * oneElement.className;
 * // => "level"
 *
 * @example
 * let listElement = createDomElement('

A

B

C

'),
 * 	manyElements = listElement.querySelectorAll("li");
 *
 * setAttrs(manyElements, {
 * 	"data-level": 42,
 * 	"class": "item"
 * });
 *
 * manyElements[0].getAttribute("data-level");
 * // => "42"
 *
 * manyElements[1].getAttribute("data-level");
 * // => "42"
 *
 * manyElements[0].className;
 * // => "item"
 *
 * manyElements[1].className;
 * // => "item"
 */
const setAttrs = (domEls, attrObj) => {
	Object.keys(attrObj).forEach(attrKey => setAttr(domEls, attrKey, attrObj[attrKey]));
};

export default setAttrs;


text:
import removeAttr from "./removeAttr.js";

/**
 * The same as [`removeAttr()`](#removeattr), except it takes an
 * array with attributes to be removed.
 *
 * @category DOM
 * @param {(HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements.
 * @param {Array.<string>} attrArr The array with attributes to be removed.
 *
 * @example
 * let oneElement = createDomElement('
Level 42
');
 *
 * removeAttrs(oneElement, ["data-level", "class"]);
 *
 * oneElement.getAttribute("data-level");
 * // => null
 *
 * oneElement.dataset.level;
 * // => undefined
 *
 * oneElement.getAttribute("class");
 * // => null
 *
 * oneElement.className;
 * // => ""
 *
 * @example
 * let listHtml = '

A

B

',
 * 	listElement = createDomElement(listHtml),
 * 	manyElements = listElement.querySelectorAll("li");
 *
 * removeAttrs(manyElements, ["data-level", "class"]);
 *
 * manyElements[0].getAttribute("data-level");
 * // => null
 *
 * manyElements[1].getAttribute("data-level");
 * // => null
 *
 * manyElements[0].className;
 * // => ""
 *
 * manyElements[1].className;
 * // => ""
 */
const removeAttrs = (domEls, attrArr) => {
	attrArr.forEach(attrName => removeAttr(domEls, attrName));
};

export default removeAttrs;


text:
import selfAndParents from "./selfAndParents.js";

/**
 * Returns an array with all DOM elements affected by an event.
 * The function serves as a polyfill for
 * [`Event.composedPath()`](https://dom.spec.whatwg.org/#dom-event-composedpath).
 *
 * @category Event
 * @param {Event} evt The triggered event.
 * @return {Array.<HTMLElement>} The DOM elements affected by the event.
 *
 * @example
 * let domChild = document.createElement("div"),
 * 	domParent = document.createElement("div"),
 * 	domGrandparent = document.createElement("div"),
 * 	body = document.body,
 * 	html = document.querySelector("html");
 *
 * domParent.appendChild(domChild);
 * domGrandparent.appendChild(domParent);
 * body.appendChild(domGrandparent);
 *
 * domChild.addEventListener("click", dealWithClick);
 * const dealWithClick = evt => getEventPath(evt);
 *
 * // when domChild is clicked:
 * // => [domChild, domParent, domGrandparent, body, html, document, window]
 */
const getEventPath = evt => {
	let path = (evt.composedPath && evt.composedPath()) || evt.path,
		target = evt.target;

	if (target == null) {
		return undefined;
	}

	if (path != null) {
		path = (!path.includes(window)) ? path.concat([window]) : path;
		return path;
	}

	if (target === window) {
		return [window];
	}

	return selfAndParents(target).concat([window]);
};

export default getEventPath;


text:
import _reactToEvent from "./internal/event/_reactToEvent.js";

/**
 * Adds one or more event listeners to one or more DOM elements at once.
 * The function is a wrapper for
 * [`Element.addEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
 * that accepts a space-separated event names string and a group
 * of target DOM elements.
 *
 * @category Event
 * @param {(Window|HTMLDocument|HTMLElement|HTMLCollection|NodeList|Array.<HTMLElement>|Set.<HTMLElement>)} domEls One or more DOM elements, including `document` and `window`.
 * @param {string} eventStr The event names string.
 * @param {Function} callback The function to be exectuted when the event is dispatched.
 * @param {Boolean} [useCapture = false] The event phase to be listened for.
 *
 * @example
 *
 * let oneElement = document.querySelector("a");
 * let manyElements = document.querySelectorAll("a");
 *
 * listen(oneElement, "click", reactToClick, true);
 * listen(manyElements, "click", reactToClick);
 * listen(window, "load resize", reactToLoadAndResize);
 */
const listen = (domEls, eventStr, callback, useCapture = false) => _reactToEvent("addEventListener", domEls, eventStr, callback, useCapture);

export default listen;


text:
import _sliceOnOccurrence from "./internal/string/_sliceOnOccurrence.js";

/**
 * Returns the string formed by the characters **after
 * the first occurrence** of the delimiter in a base string.
 * If the delimiter is not found, the function returns `undefined`.
 *
 * @category String
 *
 * @param  {string} str The base string.
 * @param  {string} delimiter The delimiter string.
 * @return {string}
 * @public
 *
 * @example
 * afterFirst("parallelepiped", "le");
 * // => "lepiped"
 */
const afterFirst = (str, delimiter) => _sliceOnOccurrence("after", "first", str, delimiter);

export default afterFirst;


text:
import _getCoordsFromElement from "./internal/geometry/_getCoordsFromElement.js";
import _getCoordsFromElementOrObjectOrWindow from "./internal/geometry/_getCoordsFromElementOrObjectOrWindow.js";
import _getVerticalAxisInfo from "./internal/geometry/_getVerticalAxisInfo.js";
import _getHorizontalAxisInfo from "./internal/geometry/_getHorizontalAxisInfo.js";

/**
 * @typedef {Object} ClippingObject
 * @property {boolean} isOffTop Above and off the mask.
 * @property {boolean} isOffBottom Below and off the mask.
 * @property {boolean} isOffLeft On the left and off the mask.
 * @property {boolean} isOffRight On the right and off the mask.
 * @property {boolean} isOff Off the mask.
 * @property {boolean} isClippedTop Above and intersecting with the mask.
 * @property {boolean} isClippedBottom Below and intersecting with the mask.
 * @property {boolean} isClippedLeft On the left and intersecting with the mask.
 * @property {boolean} isClippedRight On the right and intersecting with the mask.
 * @property {boolean} isClipped Intersecting with the mask.
 * @property {boolean} isFullyVisible Fully visible inside the mask.
 * @property {boolean} isPartiallyVisible Alias for `isClipped`.
 * @property {boolean} isInvisible Alias for `isOff`.
 * @property {boolean} isAsVisibleAsPossible As visible as possible (the element is taller or wider than the mask).
 * @property {boolean} isNotAsVisibleAsPossible Not as visible as possible (the element is taller or wider than the mask).
 */

/**
 * Given a DOM element, returns an object with position
 * and clipping information relative to a mask, defined
 * by the second parameter, or to the viewport, if the
 * second parameter is omitted.
 *
 * The mask can be either a DOM element or an object
 * containing numeric values for "top", "bottom",
 * "left" and "right" properties, like a
 * [`DOMRect`](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect).
 *
 * @category Geometry
 *
 * @param  {HTMLElement} domEl The DOM element.
 * @param  {(HTMLElement|Object)} [maskDef] The mask definition.
 * @return {ClippingObject} Position and clipping information relative to a mask (see table below).
 *
 * @example
 * let domEl = document.createElement("div");
 *
 * domEl.style.position = "fixed";
 * domEl.style.top = "-50px";
 * domEl.style.left = "-50px";
 * domEl.style.width = "200px";
 * domEl.style.height = "200px";
 *
 * document.body.appendChild(domEl);
 *
 * let info = getClippingInfo(domEl);
 *
 * info.isClippedTop;
 * // => true
 *
 * info.isClippedLeft;
 * // => true
 *
 * info.isFullyVisible;
 * // => false
 *
 * info.isPartiallyVisible;
 * // => true
 *
 * info.isInvisible;
 * // => false
 */
const getClippingInfo = (domEl, maskDef) => {
	let domCoords  = _getCoordsFromElement(domEl);
	let maskCoords = _getCoordsFromElementOrObjectOrWindow(maskDef),
		vertAxis   = _getVerticalAxisInfo(domCoords, maskCoords),
		horzAxis   = _getHorizontalAxisInfo(domCoords, maskCoords);

	let isOffTop                 = vertAxis.isOffBefore,
		isOffBottom              = vertAxis.isOffAfter,
		isOffLeft                = horzAxis.isOffBefore,
		isOffRight               = horzAxis.isOffAfter,
		isOff                    = isOffTop || isOffBottom || isOffLeft || isOffRight,
		isClippedTop             = !isOff && (vertAxis.isClippedBefore),
		isClippedBottom          = !isOff && (vertAxis.isClippedAfter),
		isClippedLeft            = !isOff && (horzAxis.isClippedBefore),
		isClippedRight           = !isOff && (horzAxis.isClippedAfter),
		isClipped                = isClippedTop || isClippedBottom || isClippedLeft || isClippedRight,
		isFullyVisible           = vertAxis.isContained && horzAxis.isContained,
		isInvisible              = isOff,
		isAsVisibleAsPossible    = isFullyVisible || (vertAxis.isWrapper && horzAxis.isWrapper) || (vertAxis.isContained && horzAxis.isWrapper) || (vertAxis.isWrapper && horzAxis.isContained),
		isNotAsVisibleAsPossible = isInvisible || !isAsVisibleAsPossible,
		isPartiallyVisible       = isClipped;

	return {
		isOffTop,
		isOffBottom,
		isOffLeft,
		isOffRight,
		isOff,
		isClippedTop,
		isClippedBottom,
		isClippedLeft,
		isClippedRight,
		isClipped,
		isFullyVisible,
		isPartiallyVisible,
		isInvisible,
		isAsVisibleAsPossible,
		isNotAsVisibleAsPossible
	};
};

export default getClippingInfo;


text:
import _getAxisInfo from "./_getAxisInfo.js";

const _getVerticalAxisInfo = (domCoords, maskCoords) => _getAxisInfo(domCoords, maskCoords, false);

export default _getVerticalAxisInfo;


text:
import _getCoords from "./_getCoords.js";

const _getCoordsFromElementOrObjectOrWindow = arg => _getCoords(arg, false);

export default _getCoordsFromElementOrObjectOrWindow;


text:
import _getAxisInfo from "./_getAxisInfo.js";

const _getHorizontalAxisInfo = (domCoords, maskCoords) => _getAxisInfo(domCoords, maskCoords, true);

export default _getHorizontalAxisInfo;


text:
const _getAxisEndProp = isHorizontal => isHorizontal ? "right" : "bottom";

export default _getAxisEndProp;


text:
import _getCoords from "./_getCoords.js";

const _getCoordsFromElement = arg => _getCoords(arg, true);

export default _getCoordsFromElement;


text:
const _getAxisStartProp = isHorizontal => isHorizontal ? "left" : "top";

export default _getAxisStartProp;


text:
import _getAxisStartProp from "./_getAxisStartProp.js";
import _getAxisEndProp from "./_getAxisEndProp.js";

const _getAxisInfo = (domCoords, maskCoords, isHorizontal) => {
	let startProp           = _getAxisStartProp(isHorizontal),
		endProp             = _getAxisEndProp(isHorizontal);

	let domStart            = domCoords[startProp],
		domEnd              = domCoords[endProp],
		maskStart           = maskCoords[startProp],
		maskEnd             = maskCoords[endProp];

	let startBeforeStart    = domStart <= maskStart,
		startBeforeStartExc = domStart < maskStart,
		startAfterStart     = domStart >= maskStart,
		startBeforeEnd      = domStart <= maskEnd,
		startAfterEnd       = domStart >= maskEnd;

	let endBeforeStart      = domEnd <= maskStart,
		endAfterStart       = domEnd >= maskStart,
		endBeforeEnd        = domEnd <= maskEnd,
		endAfterEnd         = domEnd >= maskEnd,
		endAfterEndExc      = domEnd > maskEnd;

	let isOffBefore         = startBeforeStart && endBeforeStart,
		isOffAfter          = startAfterEnd && endAfterEnd,
		isContained         = startAfterStart && endBeforeEnd,
		isWrapper           = startBeforeStart && endAfterEnd,
		isClippedBefore     = startBeforeStartExc && endAfterStart,
		isClippedAfter      = startBeforeEnd && endAfterEndExc;

	return {
		isOffBefore,
		isOffAfter,
		isContained,
		isWrapper,
		isClippedBefore,
		isClippedAfter
	};
};

export default _getAxisInfo;


text:
import _isElement from "../helpers/_isElement.js";
import _throwErrorIf from "../validation/_throwErrorIf.js";

const _getCoords = (maskDef, allowElementOnly) => {
	let maskCoords;

	if (_isElement(maskDef)) {
		maskCoords = maskDef.getBoundingClientRect();
	}
	else if (maskDef != null && !allowElementOnly) {
		maskCoords = maskDef;
	}
	else if (!allowElementOnly) {
		maskCoords = {
			top: 0,
			bottom: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
			left: 0,
			right: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
		};
	}

	if (!Number.isFinite(maskCoords.top) || !Number.isFinite(maskCoords.bottom) || !Number.isFinite(maskCoords.left) || !Number.isFinite(maskCoords.right)) {
		_throwErrorIf(allowElementOnly, `An HTMLElement is expected as parameter.`);
		_throwErrorIf(!allowElementOnly, `If passed, the optional parameter can be either an HTMLElement or an Object containing numeric values for "top", "bottom", "left" and "right" properties.`);
	}

	return maskCoords;
};

export default _getCoords;


text:
const _throwErrorIf = (condition, error) => {
	if (condition) {
		throw new Error(error);
	}
};

export default _throwErrorIf;


text:
import _splitEventStr from "./_splitEventStr.js";
import _throwErrorIf from "../validation/_throwErrorIf.js";
import _isString from "../helpers/_isString.js";
import _domElementsOrDocumentOrWindowToArray from "../dom/_domElementsOrDocumentOrWindowToArray.js";

const _reactToEvent = (methodName, domEls, eventStr, callback, useCapture) => {
	_throwErrorIf(!_isString(eventStr), "A string is expected as second parameter.");
	_splitEventStr(eventStr).forEach(eventType => _domElementsOrDocumentOrWindowToArray(domEls).forEach(domEl => domEl[methodName](eventType, callback, useCapture)));
};

export default _reactToEvent;


text:
const _splitEventStr = eventStr => eventStr.split(" ");

export default _splitEventStr;


text:
import _parseBemEntityWithFunc from "./_parseBemEntityWithFunc.js";
import _parseBemProp from "./_parseBemProp.js";

const _parseBem = (...args) => {
	return _parseBemEntityWithFunc(_parseBemProp, ...args);
};

export default _parseBem;


text:
import _joinBemEntityWithDelimiter from "./_joinBemEntityWithDelimiter.js";

function _formatBemRadical(block, element, delimiters) {
	let elementDelimiter = delimiters[0],
		elementBase = _joinBemEntityWithDelimiter(element, elementDelimiter);

	return `${block}${elementBase}`;
}

export default _formatBemRadical;


text:
import addClass from "../../addClass.js";
import removeClass from "../../removeClass.js";
import _hasNoModifiers from "./_hasNoModifiers.js";
import _hasAllModifiersSetToFalse from "./_hasAllModifiersSetToFalse.js";
import _parseModifier from "./_parseModifier.js";

function _parseBemProp(bemObj, domEl, delimiters, shouldRepeatBemRadical) {
	return function(radical) {
		let modifierObj = bemObj[radical];

		if (shouldRepeatBemRadical || _hasNoModifiers(modifierObj) || _hasAllModifiersSetToFalse(modifierObj)) {
			addClass(domEl, radical);
		}
		else {
			removeClass(domEl, radical);
		}

		_parseModifier(modifierObj, domEl, radical, delimiters);
	};
}

export default _parseBemProp;


text:
import _isString from "../helpers/_isString.js";

const _isValidDelimiterArray = delimiters => {
	return Array.isArray(delimiters) && delimiters.length === 3 && delimiters.every(delimiter => _isString(delimiter) && delimiter !== "");
};

export default _isValidDelimiterArray;


text:
import _isString from "../helpers/_isString.js";
import _isBoolean from "../helpers/_isBoolean.js";
import _isPlainObject from "../helpers/_isPlainObject.js";

const _isValidModifierObject = modifierObj => {
	return _isPlainObject(modifierObj) && Object.keys(modifierObj).every(key => {
		let prop = modifierObj[key];
		return _isBoolean(prop) || _isString(prop) || Number.isFinite(prop);
	});
};

export default _isValidModifierObject;


text:
const _hasNoModifiers = modifierObj => Object.keys(modifierObj).length === 0;

export default _hasNoModifiers;


text:
import _joinBemEntityWithDelimiter from "./_joinBemEntityWithDelimiter.js";

function _formatBemModifier(modifier, value, delimiters) {
	let modifierDelimiter = delimiters[1],
		modifierBase = _joinBemEntityWithDelimiter(modifier, modifierDelimiter);

	let valueDelimiter = delimiters[2],
		valueBase = _joinBemEntityWithDelimiter(value, valueDelimiter);

	return (value === true) ? modifierBase : (value !== false && value != null) ? `${modifierBase}${valueBase}` : "";
}

export default _formatBemModifier;


text:
const _hasAllModifiersSetToFalse = modifierObj => {
	return Object.keys(modifierObj).every(key => modifierObj[key] === false);
};

export default _hasAllModifiersSetToFalse;


text:
const _joinBemEntityWithDelimiter = (entity, delimiter) => {
	return (entity != null && entity !== "" && typeof entity !== "boolean") ? `${delimiter}${entity}` : "";
};

export default _joinBemEntityWithDelimiter;


text:
import _parseBemEntityWithFunc from "./_parseBemEntityWithFunc.js";
import _parseModifierProp from "./_parseModifierProp.js";

const _parseModifier = (...args) => _parseBemEntityWithFunc(_parseModifierProp, ...args);

export default _parseModifier;


text:
const _parseBemEntityWithFunc = (func, ...args) => Object.keys(args[0]).forEach(func(...args));

export default _parseBemEntityWithFunc;


text:
import _formatBemModifier from "./_formatBemModifier.js";

function _formatBemClassFromRadical(radical, modifier, value, delimiters) {
	let classModifier = _formatBemModifier(modifier, value, delimiters);
	return `${radical}${classModifier}`;
}

export default _formatBemClassFromRadical;


text:
import _isValidModifierObject from "./_isValidModifierObject.js";
import _isPlainObject from "../helpers/_isPlainObject.js";

const _isValidBemObject = bemObj => {
	return _isPlainObject(bemObj) && Object.keys(bemObj).every(key => _isValidModifierObject(bemObj[key]));
};

export default _isValidBemObject;


text:
import addClass from "../../addClass.js";
import removeClass from "../../removeClass.js";
import _removeClassesBeginningWithButNot from "../classname/_removeClassesBeginningWithButNot.js";
import formatBemClass from "../../formatBemClass.js";

function _parseModifierProp(modifierObj, domEl, radical, delimiters) {
	return function(modifier) {
		let blockDelimiter = delimiters[0],
			block = radical.split(blockDelimiter)[0],
			element = radical.split(blockDelimiter)[1];

		let value = modifierObj[modifier];

		let removedBemClass = formatBemClass(block, element, modifier, true, delimiters),
			addedBemClass = formatBemClass(block, element, modifier, value, delimiters);

		if (value === false) {
			removeClass(domEl, removedBemClass);
		}
		else if (value !== true) {
			_removeClassesBeginningWithButNot(domEl, removedBemClass);
		}

		if (value !== false) {
			addClass(domEl, addedBemClass);
		}
	};
}

export default _parseModifierProp;


text:
import _isElement from "../helpers/_isElement.js";
import _isValidBemObject from "./_isValidBemObject.js";
import _isValidDelimiterArray from "./_isValidDelimiterArray.js";
import _throwErrorIf from "../validation/_throwErrorIf.js";

const _validateModifyBemClassArgs = (domEl, bemObj, delimiters) => {
	_throwErrorIf(!_isElement(domEl), `An HTMLElement is expected as the first parameter.`);
	_throwErrorIf(!_isValidBemObject(bemObj), `An object describing BEM class changes is expected as the second parameter.`);
	_throwErrorIf(!_isValidDelimiterArray(delimiters), `An array with three strings representing BEM delimiters is expected as the third parameter.`);
};

export default _validateModifyBemClassArgs;


text:
const _isPlainObject = obj =>
	obj != null && typeof obj === "object" &&
	(obj.constructor === Object || obj.constructor == null) &&
	Object.prototype.toString.call(obj) === "[object Object]";

export default _isPlainObject;


text:
import _parsePath from "./_parsePath.js";
import _isPlainObject from "./_isPlainObject.js";

const _simpleSet = (obj, path, value) =>
	_parsePath(path).reduce((obj, key, index, arr) => {
		let isLast = (index === arr.length - 1);

		if (!obj.hasOwnProperty(key) || (!isLast && !_isPlainObject(obj[key]))) {
			obj[key] = {};
		}

		return (!isLast) ? obj[key] : obj[key] = value;
	}, obj);

export default _simpleSet;


text:
const _parsePath = path =>
	Array.isArray(path) ? path : `${path}`.split(".");

export default _parsePath;


text:
const _isBoolean = arg =>
	arg === true || arg === false;

export default _isBoolean;


text:
import _parsePath from "./_parsePath.js";

const _simpleAt = (obj, path) =>
	_parsePath(path).reduce((obj, key) => {
		return (obj != null && obj.hasOwnProperty(key)) ? obj[key] : undefined;
	}, obj);

export default _simpleAt;


text:
const _random = (min, max) =>
	Math.floor(Math.random() * (max - min + 1)) + min;

export default _random;


text:
const _isElement = arg =>
	arg != null && typeof arg === "object" && arg.nodeType === Node.ELEMENT_NODE &&
	typeof arg.style === "object" && typeof arg.ownerDocument === "object";

export default _isElement;


text:
const _isString = arg =>
	typeof arg === 'string' || arg instanceof String;

export default _isString;


text:
import _simpleAt from "../helpers/_simpleAt.js";

const _recursiveSort = fields => (objA, objB) => {
	let field = fields[0],
		path = field.path,
		result = field.comparator(_simpleAt(objA, path), _simpleAt(objB, path)),
		nextFields = fields.slice(1);

	if (result !== 0 || nextFields.length === 0) {
		return result;
	}

	return _recursiveSort(nextFields)(objA, objB);
};

export default _recursiveSort;


text:
import _defaultComparator from "./_defaultComparator.js";

const _customComparator = (primer, reverse) => {
	let result = _defaultComparator;

	if (primer) {
		result = (a, b) => _defaultComparator(primer(a), primer(b));
	}

	if (reverse) {
		return (a, b) => -1 * result(a, b);
	}

	return result;
};

export default _customComparator;


text:
import _parseSortField from "./_parseSortField.js";

const _parseSortFields = fields => fields.map(_parseSortField);

export default _parseSortFields;


text:
import _defaultComparator from "./_defaultComparator.js";
import _customComparator from "./_customComparator.js";
import _isString from "../helpers/_isString.js";

const _parseSortField = field => {
	let useDefault = _isString(field);

	return {
		path: (useDefault) ? field : field.path,
		comparator: (useDefault) ? _defaultComparator : _customComparator(field.primer, field.reverse)
	};
};

export default _parseSortField;


text:
import _isString from "../helpers/_isString.js";

const _defaultComparator = (a, b) => (_isString(a) && _isString(b)) ?
	a.localeCompare(b) : (a == b) ? 0 : (a < b) ? -1 : 1;

export default _defaultComparator;


text:
import _removeClassesBeginningWithButNotBase from "./_removeClassesBeginningWithButNotBase.js";
import _domElementsToArray from "../dom/_domElementsToArray.js";

const _removeClassesBeginningWithButNot = (domEls, str) => {
	_domElementsToArray(domEls).forEach(domEl => _removeClassesBeginningWithButNotBase(domEl, str));
};

export default _removeClassesBeginningWithButNot;


text:
const _changeClassWithMethod = (domEl, str, methodName) => {
	if (str) {
		domEl.classList[methodName](str);
	}
};

export default _changeClassWithMethod;


text:
import removeClass from "../../removeClass.js";

const _removeClassesBeginningWithButNotBase = (domEl, str) => {
	for (let i = domEl.classList.length - 1; i >= 0; i--) {
		let currentClass = domEl.classList.item(i);

		if (currentClass !== str && currentClass.startsWith(str)) {
			removeClass(domEl, currentClass);
		}
	}
	return domEl;
};

export default _removeClassesBeginningWithButNotBase;


text:
import _isElement from "../helpers/_isElement.js";
import _isElementOrDocumentOrWindow from "./_isElementOrDocumentOrWindow.js";
import _throwErrorIf from "../validation/_throwErrorIf.js";

const _domElementsToArray = (arg, allowDocumentAndWindow = false) => {
	let result = arg,
		isDom = allowDocumentAndWindow ? _isElementOrDocumentOrWindow : _isElement,
		errorMsg = allowDocumentAndWindow ? "One or more HTMLElements are expected as the first parameter." : "One or more HTMLElements, including document or window, are expected as the first parameter.";

	if (arg == null) {
		return [];
	}

	if (isDom(arg)) {
		result = [arg];
	}
	else if (arg != null && (typeof arg.length === "number" || typeof arg.size === "number")) {
		result = Array.from(arg);
	}

	_throwErrorIf(!Array.isArray(result) || result.some(item => !isDom(item)), errorMsg);

	return result;
};

export default _domElementsToArray;


text:
import _throwErrorIf from "../validation/_throwErrorIf.js";

const _createDomElement = htmlStr => {
	let domEl = document.createElement("div");
	domEl.innerHTML = htmlStr;

	_throwErrorIf(domEl.children.length !== 1, "A string defining a single HTMLElement, with or without children, is expected as parameter.");

	return domEl.children[0];
};

export default _createDomElement;


text:
import _isElement from "../helpers/_isElement.js";

const _isElementOrDocumentOrWindow = arg => _isElement(arg) || arg === document || arg === window;

export default _isElementOrDocumentOrWindow;


text:
import _domToArray from "./_domToArray.js";

const _domElementsToArray = arg => _domToArray(arg, false);

export default _domElementsToArray;


text:
const _createFragment = htmlStr => {
	let domEl = document.createElement("div"),
		result = document.createDocumentFragment();

	domEl.innerHTML = htmlStr;

	Array.from(domEl.children).forEach(child => {
		result.appendChild(child);
	});

	return result;
};

export default _createFragment;


text:
// as seen on https://github.com/kangax/html-minifier/issues/63/#issuecomment-37772698

const _isBooleanAttribute = attr => {
	return (/^(?:allowfullscreen|async|autofocus|autoplay|checked|compact|controls|declare|default|defaultchecked|defaultmuted|defaultselected|defer|disabled|draggable|enabled|formnovalidate|hidden|indeterminate|inert|ismap|itemscope|loop|multiple|muted|nohref|noresize|noshade|novalidate|nowrap|open|pauseonexit|readonly|required|reversed|scoped|seamless|selected|sortable|spellcheck|translate|truespeed|typemustmatch|visible)$/).test(attr);
};

export default _isBooleanAttribute;


text:
const _setAttrBase = (domEl, attrName, value) => {
	if (value != null && value !== "") {
		if (typeof value === "boolean") {
			if (value === false) {
				domEl.removeAttribute(attrName);
			}
			else {
				domEl.setAttribute(attrName, "");
			}
		}
		else {
			domEl.setAttribute(attrName, value);
		}
	}
};

export default _setAttrBase;


text:
import _domToArray from "./_domToArray.js";

const _domElementsOrDocumentOrWindowToArray = arg => _domToArray(arg, true);

export default _domElementsOrDocumentOrWindowToArray;


text:
import _isString from "../helpers/_isString.js";
import _throwErrorIf from "../validation/_throwErrorIf.js";

const _sliceOnOccurrence = (type, position, str, delimiter) => {
	_throwErrorIf(!_isString(str), "A string is expected as the first parameter.");

	let index = (position === "first") ? str.indexOf(delimiter) : str.lastIndexOf(delimiter);

	if (index === -1) {
		return undefined;
	}

	return (type === "before") ? str.substr(0, index) : str.substr(index + delimiter.length);
};

export default _sliceOnOccurrence;


text:
MOEX ISS API
============

.. image:: https://github.com/WLM1ke/apimoex/workflows/tests/badge.svg
    :target: https://github.com/WLM1ke/apimoex/actions
.. image:: https://codecov.io/gh/WLM1ke/apimoex/branch/master/graph/badge.svg
    :target: https://codecov.io/gh/WLM1ke/apimoex
.. image:: https://badge.fury.io/py/apimoex.svg
    :target: https://badge.fury.io/py/apimoex

Реализация части запросов к `MOEX Informational & Statistical Server <https://www.moex.com/a2193>`_.

Документация
------------

https://wlm1ke.github.io/apimoex/

Основные возможности
--------------------

Реализовано несколько функций-запросов информации о торгуемых акциях и их исторических котировках, результаты которых
напрямую конвертируются в pandas.DataFrame.

Работа функций базируется на универсальном клиенте, позволяющем осуществлять произвольные запросы к MOEX ISS, поэтому
перечень доступных функций-запросов может быть легко расширен. При необходимости добавления функций воспользуйтесь
`Issues <https://github.com/WLM1ke/apimoex/issues>`_ на GitHub с указанием ссылки на описание запроса:

* Полный перечень возможных `запросов <https://iss.moex.com/iss/reference/>`_ к MOEX ISS
* Официальное `Руководство разработчика <https://fs.moex.com/files/6523>`_ с дополнительной информацией

Начало работы
=============

Установка
---------

.. code-block:: Bash

   $ pip install apimoex

Пример использования реализованных запросов
-------------------------------------------

История котировок `SNGSP в режиме TQBR <https://www.moex.com/ru/issue.aspx?board=TQBR&code=SNGSP>`_:

.. code-block:: python

   import requests

   import apimoex
   import pandas as pd

   with requests.Session() as session:
       data = apimoex.get_board_history(session, 'SNGSP')
       df = pd.DataFrame(data)
       df.set_index('TRADEDATE', inplace=True)
       print(df.head(), '\n')
       print(df.tail(), '\n')
       df.info()

.. code-block::

               BOARDID  CLOSE    VOLUME         VALUE
    TRADEDATE
    2014-06-09    TQBR  27.48  12674200  3.484352e+08
    2014-06-10    TQBR  27.55  14035900  3.856417e+08
    2014-06-11    TQBR  28.15  27208800  7.602146e+08
    2014-06-16    TQBR  28.27  68059900  1.913160e+09
    2014-06-17    TQBR  28.20  22101600  6.292844e+08

               BOARDID   CLOSE     VOLUME         VALUE
    TRADEDATE
    2019-09-04    TQBR  38.060  243010500  9.348435e+09
    2019-09-05    TQBR  36.140  129366600  4.704949e+09
    2019-09-06    TQBR  35.475   62389000  2.201887e+09
    2019-09-09    TQBR  34.570   54331300  1.905837e+09
    2019-09-10    TQBR  35.250   45966000  1.605849e+09

    <class 'pandas.core.frame.DataFrame'>
    Index: 1326 entries, 2014-06-09 to 2019-09-10
    Data columns (total 4 columns):
    BOARDID    1326 non-null object
    CLOSE      1326 non-null float64
    VOLUME     1326 non-null int64
    VALUE      1326 non-null float64
    dtypes: float64(2), int64(1), object(1)
    memory usage: 51.8+ KB

Пример реализации запроса с помощью клиента
-------------------------------------------

Перечень акций, торгующихся в режиме TQBR (`описание запроса <https://iss.moex.com/iss/reference/32>`_):

.. code-block:: python

   import requests

   import apimoex
   import pandas as pd

   request_url = ('https://iss.moex.com/iss/engines/stock/'
                  'markets/shares/boards/TQBR/securities.json')
   arguments = {'securities.columns': ('SECID,'
                                       'REGNUMBER,'
                                       'LOTSIZE,'
                                       'SHORTNAME')}
   with requests.Session() as session:
       iss = apimoex.ISSClient(session, request_url, arguments)
       data = iss.get()
       df = pd.DataFrame(data['securities'])
       df.set_index('SECID', inplace=True)
       print(df.head(), '\n')
       print(df.tail(), '\n')
       df.info()

.. code-block::

              REGNUMBER  LOTSIZE   SHORTNAME
    SECID
    ABRD   1-02-12500-A       10  АбрауДюрсо
    AFKS   1-05-01669-A      100  Система ао
    AFLT   1-01-00010-A       10    Аэрофлот
    AGRO           None        1    AGRO-гдр
    AKRN   1-03-00207-A        1       Акрон

              REGNUMBER  LOTSIZE   SHORTNAME
    SECID
    YNDX           None        1  Yandex clA
    YRSB   1-01-50099-A       10     ТНСэнЯр
    YRSBP  2-01-50099-A       10   ТНСэнЯр-п
    ZILL   1-02-00036-A        1      ЗИЛ ао
    ZVEZ   1-01-00169-D     1000   ЗВЕЗДА ао

    <class 'pandas.core.frame.DataFrame'>
    Index: 264 entries, ABRD to ZVEZ
    Data columns (total 3 columns):
    REGNUMBER    255 non-null object
    LOTSIZE      264 non-null int64
    SHORTNAME    264 non-null object
    dtypes: int64(1), object(2)
    memory usage: 8.2+ KB

repo_language: Python

mime_type: text/plain


text:
requests
pytest
pytest-cov
sphinx
aiohttp_theme
pandas


text:
import pathlib
import re
import sys

import setuptools

name = "apimoex"
python_minimal = "3.6"

if sys.version_info < tuple(int(i) for i in python_minimal.split(".")):
    raise RuntimeError(f"{name} requires Python {python_minimal}+")

with open(pathlib.Path(__file__).parent / "apimoex" / "__init__.py") as file:
    try:
        version = re.search(r"^__version__ = \"(.+)\"$", file.read(), re.M)[1]
    except IndexError:
        raise RuntimeError("Unable to determine version.")

with open("README.rst") as file:
    long_description = file.read()

setuptools.setup(
    name=name,
    version=version,
    description="MOEX ISS API",
    long_description=long_description,
    long_description_content_type="text/x-rst",
    url="https://wlm1ke.github.io/apimoex/",
    author="Mikhail Korotkov aka WLMike",
    author_email="wlmike@gmail.com",
    license="http://unlicense.org",
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "Environment :: Other Environment",
        "Intended Audience :: Developers",
        "License :: Public Domain",
        "Natural Language :: Russian",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: Implementation :: CPython",
        "Topic :: Utilities",
    ],
    keywords="moex iss api",
    project_urls={"Source": "https://github.com/WLM1ke/apimoex"},
    packages=setuptools.find_packages(exclude=["tests"]),
    install_requires=["requests"],
    python_requires=f">={python_minimal}",
)


text:
MOEX ISS API
====================

Реализация части  запросов к `MOEX Informational & Statistical Server <https://www.moex.com/a2193>`_.

Основные возможности
--------------------
Реализовано несколько функций-запросов информации о торгуемых акциях и их исторических котировках, результаты которых
напрямую конвертируются в pandas.DataFrame.

Работа функций базируется на универсальном клиенте, позволяющем осуществлять произвольные запросы к MOEX ISS, поэтому
перечень доступных функций-запросов может быть легко расширен. При необходимости добавления функций воспользуйтесь
`Issues <https://github.com/WLM1ke/aiomoex/issues>`_ на GitHub с указанием ссылки на описание запроса:

* Полный перечень возможных `запросов <https://iss.moex.com/iss/reference/>`_ к MOEX ISS
* Официальное `Руководство разработчика <https://fs.moex.com/files/6523>`_ с дополнительной информацией

Оглавление
----------
.. toctree::
   :maxdepth: 3

   getting_started
   api
   change_log


text:
Список изменений
================

1.3.0 (2023-04-20)
------------------
* Добавлен запрос для получения состава индекса

1.2.0 (2020-02-03)
------------------
* Добавлен запрос для получения спецификации инструмента

1.1.2 (2019-09-15)
------------------
* Корректная обработка запросов с пустыми таблицами

1.1.1 (2019-09-13)
------------------
* Минорная правка

1.1.0 (2019-09-13)
------------------
* Добавлена возможность выбора загружаемых столбцов для get_board_candles и get_market_candles

1.0.2 (2019-09-12)
------------------
* Уточнены типы аргументов

1.0.1 (2019-09-11)
------------------
* Исправления в readme

1.0.0 (2019-09-11)
------------------
* Начальная версия


text:
import os
import re
import sys

_package_name = "apimoex"

_route_path = os.path.abspath("../")
sys.path.insert(0, _route_path)
_version_path = os.path.abspath(os.path.join(_route_path, _package_name, "__init__.py"))
with open(_version_path) as file:
    try:
        _version_info = re.search(
            r"^__version__ = \""
            r"(?P<major>\d+)"
            r"\.(?P<minor>\d+)"
            r"\.(?P<patch>\d+)\"$",
            file.read(),
            re.M,
        ).groupdict()
    except IndexError:
        raise RuntimeError("Unable to determine version.")

version = "{major}.{minor}".format(**_version_info)
release = "{major}.{minor}.{patch}".format(**_version_info)

extensions = ["sphinx.ext.autodoc", "sphinx.ext.githubpages"]
autodoc_member_order = "bysource"
templates_path = ["templates"]
html_static_path = ["static"]

source_suffix = ".rst"
master_doc = "index"
project = _package_name
copyright = "2019, Mikhail Korotkov aka WLMike"
author = "Mikhail Korotkov aka WLMike"
language = "ru"
exclude_patterns = ["build"]
highlight_language = "default"
html_theme = "aiohttp_theme"

html_theme_options = {
    "logo": "",
    "description": "MOEX ISS API",
    "canonical_url": "https://wlm1ke.github.io/apimoex",
    "github_user": "WLM1ke",
    "github_repo": "apimoex",
    "github_button": False,
    "github_type": "",
    "github_banner": True,
    "travis_button": False,
    "badges": [
        {
            "image": "https://github.com/WLM1ke/apimoex/workflows/tests/badge.svg",
            "target": "https://github.com/WLM1ke/apimoex/actions",
            "height": "20",
            "alt": "Tests status",
        },
        {
            "image": "https://codecov.io/gh/WLM1ke/apimoex/branch/master/graph/badge.svg",
            "target": "https://codecov.io/gh/WLM1ke/apimoex",
            "height": "20",
            "alt": "Code coverage status",
        },
        {
            "image": "https://badge.fury.io/py/apimoex.svg",
            "target": "https://badge.fury.io/py/apimoex",
            "height": "20",
            "alt": "Latest PyPI package version",
        },
    ],
    "sidebar_collapse": False,
}

html_sidebars = {"**": ["about.html", "navigation.html"]}


text:
<html>
<head>
<meta http-equiv="refresh" content="0; url=./build/html/index.html"/>
</head>
<body></body>
</html>


text:
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
SOURCEDIR     = .
BUILDDIR      = build

# Put it first so that "make" without argument is like "make help".
html:
	@$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: html Makefile


text:
Начало работы
=============
Установка
---------

.. code-block:: Bash

   $ pip install apimoex

Пример использования реализованных запросов
-------------------------------------------
История котировок SNGSP в режиме TQBR::

   import requests

   import apimoex
   import pandas as pd

   with requests.Session() as session:
       data = apimoex.get_board_history(session, 'SNGSP')
       df = pd.DataFrame(data)
       df.set_index('TRADEDATE', inplace=True)
       print(df.head(), '\n')
       print(df.tail(), '\n')
       df.info()

.. code-block:: default

               BOARDID  CLOSE    VOLUME         VALUE
    TRADEDATE
    2014-06-09    TQBR  27.48  12674200  3.484352e+08
    2014-06-10    TQBR  27.55  14035900  3.856417e+08
    2014-06-11    TQBR  28.15  27208800  7.602146e+08
    2014-06-16    TQBR  28.27  68059900  1.913160e+09
    2014-06-17    TQBR  28.20  22101600  6.292844e+08

               BOARDID   CLOSE     VOLUME         VALUE
    TRADEDATE
    2019-09-04    TQBR  38.060  243010500  9.348435e+09
    2019-09-05    TQBR  36.140  129366600  4.704949e+09
    2019-09-06    TQBR  35.475   62389000  2.201887e+09
    2019-09-09    TQBR  34.570   54331300  1.905837e+09
    2019-09-10    TQBR  35.250   45966000  1.605849e+09

    <class 'pandas.core.frame.DataFrame'>
    Index: 1326 entries, 2014-06-09 to 2019-09-10
    Data columns (total 4 columns):
    BOARDID    1326 non-null object
    CLOSE      1326 non-null float64
    VOLUME     1326 non-null int64
    VALUE      1326 non-null float64
    dtypes: float64(2), int64(1), object(1)
    memory usage: 51.8+ KB

Пример реализации запроса с помощью клиента
-------------------------------------------
Перечень акций, торгующихся в режиме TQBR (`описание запроса <https://iss.moex.com/iss/reference/32>`_)::

   import requests

   import apimoex
   import pandas as pd

   request_url = ('https://iss.moex.com/iss/engines/stock/'
                  'markets/shares/boards/TQBR/securities.json')
   arguments = {'securities.columns': ('SECID,'
                                       'REGNUMBER,'
                                       'LOTSIZE,'
                                       'SHORTNAME')}
   with requests.Session() as session:
       iss = apimoex.ISSClient(session, request_url, arguments)
       data = iss.get()
       df = pd.DataFrame(data['securities'])
       df.set_index('SECID', inplace=True)
       print(df.head(), '\n')
       print(df.tail(), '\n')
       df.info()

.. code-block:: default

              REGNUMBER  LOTSIZE   SHORTNAME
    SECID
    ABRD   1-02-12500-A       10  АбрауДюрсо
    AFKS   1-05-01669-A      100  Система ао
    AFLT   1-01-00010-A       10    Аэрофлот
    AGRO           None        1    AGRO-гдр
    AKRN   1-03-00207-A        1       Акрон

              REGNUMBER  LOTSIZE   SHORTNAME
    SECID
    YNDX           None        1  Yandex clA
    YRSB   1-01-50099-A       10     ТНСэнЯр
    YRSBP  2-01-50099-A       10   ТНСэнЯр-п
    ZILL   1-02-00036-A        1      ЗИЛ ао
    ZVEZ   1-01-00169-D     1000   ЗВЕЗДА ао

    <class 'pandas.core.frame.DataFrame'>
    Index: 264 entries, ABRD to ZVEZ
    Data columns (total 3 columns):
    REGNUMBER    255 non-null object
    LOTSIZE      264 non-null int64
    SHORTNAME    264 non-null object
    dtypes: int64(1), object(2)
    memory usage: 8.2+ KB


text:
Справочник API
==============

Функции-запросы
----------------

Справочная информация
^^^^^^^^^^^^^^^^^^^^^
Функции из данного раздела носят вспомогательный характер и нужны для получения данных для построения остальных
запросов.

.. autofunction:: apimoex.get_reference

.. autofunction:: apimoex.find_securities

.. autofunction:: apimoex.find_security_description

.. autofunction:: apimoex.get_index_tickers

Исторические данные по свечкам
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MOEX ISS формирует свечки в формате HLOCV, при этом используются следующие условные числовые коды:

* 1 - 1 минута
* 10 - 10 минут
* 60 - 1 час
* 24 - 1 день
* 7 - 1 неделя
* 31 - 1 месяц
* 4 - 1 квартал

Для разных свечек и инструментов доступна информация за разные интервалы дат, уточнить которые можно с помощью функции
get_market_candle_borders() или get_board_candle_borders(), а получить исторические значения свечек с помощью
get_market_candles() или get_board_candles(), используя числовой код размера свечки.

.. autofunction:: apimoex.get_market_candle_borders

.. autofunction:: apimoex.get_board_candle_borders

.. autofunction:: apimoex.get_market_candles

.. autofunction:: apimoex.get_board_candles

Исторические данные по дневным котировкам
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
В отличие от свечек, функции данного раздела предоставляют много вспомогательной информации и имеют более глубокую историю.
Функция get_board_dates() позволяет проверить для каких дат имеются исторические котировки.
Функция get_board_securities() позволяет получить данные о размере лотов и прочей информации по всем торгуемым бумагам в
конкретном режиме торгов. Функции get_market_history() и get_board_history() позволяют запросить исторические дневные
котировки с различной вспомогательной информацией для конкретной бумаги для всех режимов торгов рынка или для
конкретного режима торгов, соответственно.

.. autofunction:: apimoex.get_board_dates

.. autofunction:: apimoex.get_board_securities

.. autofunction:: apimoex.get_market_history

.. autofunction:: apimoex.get_board_history

Реализация произвольного запроса
--------------------------------
Для осуществления запроса необходимо начать сессию соединений с MOEX ISS и передать клиенту корректный url и
дополнительные параметры:

* Полный перечень возможных `запросов <https://iss.moex.com/iss/reference/>`_ к MOEX ISS
* Официальное `Руководство разработчика <https://fs.moex.com/files/6523>`_ с дополнительной информацией

.. autoclass:: apimoex.ISSClient
    :members:
    :show-inheritance:


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />

    <title>Список изменений — документация apimoex 1.2.0</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/aiohttp.css" />

    <link rel="index" title="Алфавитный указатель" href="genindex.html" />
    <link rel="search" title="Поиск" href="search.html" />
    <link rel="prev" title="Справочник API" href="api.html" />

<link rel="stylesheet" href="_static/custom.css" type="text/css" />

<link rel="canonical" href="https://wlm1ke.github.io/apimoexchange_log.html"/>

<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
<link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet">

Список изменений¶

1.3.0 (2023-04-20)¶

Добавлен запрос для получения состава индекса

1.2.0 (2020-02-03)¶

Добавлен запрос для получения спецификации инструмента

1.1.2 (2019-09-15)¶

Корректная обработка запросов с пустыми таблицами

1.1.1 (2019-09-13)¶

Минорная правка

1.1.0 (2019-09-13)¶

Добавлена возможность выбора загружаемых столбцов для get_board_candles и get_market_candles

1.0.2 (2019-09-12)¶

Уточнены типы аргументов

1.0.1 (2019-09-11)¶

Исправления в readme

1.0.0 (2019-09-11)¶

Начальная версия

apimoex

MOEX ISS API

Навигация

Начало работы

Установка

Пример использования реализованных запросов

Пример реализации запроса с помощью клиента

Справочник API

Функции-запросы

Справочная информация

Исторические данные по свечкам

Исторические данные по дневным котировкам

Реализация произвольного запроса

ISSClient

Список изменений

1.3.0 (2023-04-20)

1.2.0 (2020-02-03)

1.1.2 (2019-09-15)

1.1.1 (2019-09-13)

1.1.0 (2019-09-13)

1.0.2 (2019-09-12)

1.0.1 (2019-09-11)

1.0.0 (2019-09-11)

      ©2019, Mikhail Korotkov aka WLMike.

      |
      Powered by Sphinx 6.1.3

      |
      Page source


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />

    <title>MOEX ISS API — документация apimoex 1.2.0</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/aiohttp.css" />

    <link rel="index" title="Алфавитный указатель" href="genindex.html" />
    <link rel="search" title="Поиск" href="search.html" />
    <link rel="next" title="Начало работы" href="getting_started.html" />

<link rel="stylesheet" href="_static/custom.css" type="text/css" />

<link rel="canonical" href="https://wlm1ke.github.io/apimoexindex.html"/>

<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
<link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet">

MOEX ISS API¶

Реализация части  запросов к MOEX Informational & Statistical Server.

Основные возможности¶

Реализовано несколько функций-запросов информации о торгуемых акциях и их исторических котировках, результаты которых
напрямую конвертируются в pandas.DataFrame.

Работа функций базируется на универсальном клиенте, позволяющем осуществлять произвольные запросы к MOEX ISS, поэтому
перечень доступных функций-запросов может быть легко расширен. При необходимости добавления функций воспользуйтесь
Issues на GitHub с указанием ссылки на описание запроса:

Полный перечень возможных запросов к MOEX ISS

Официальное Руководство разработчика с дополнительной информацией

Оглавление¶

Начало работы

Установка

Пример использования реализованных запросов

Пример реализации запроса с помощью клиента

Справочник API

Функции-запросы

Справочная информация

Исторические данные по свечкам

Исторические данные по дневным котировкам

Реализация произвольного запроса

ISSClient

Список изменений

1.3.0 (2023-04-20)

1.2.0 (2020-02-03)

1.1.2 (2019-09-15)

1.1.1 (2019-09-13)

1.1.0 (2019-09-13)

1.0.2 (2019-09-12)

1.0.1 (2019-09-11)

1.0.0 (2019-09-11)

apimoex

MOEX ISS API

Навигация

Начало работы

Установка

Пример использования реализованных запросов

Пример реализации запроса с помощью клиента

Справочник API

Функции-запросы

Справочная информация

Исторические данные по свечкам

Исторические данные по дневным котировкам

Реализация произвольного запроса

ISSClient

Список изменений

1.3.0 (2023-04-20)

1.2.0 (2020-02-03)

1.1.2 (2019-09-15)

1.1.1 (2019-09-13)

1.1.0 (2019-09-13)

1.0.2 (2019-09-12)

1.0.1 (2019-09-11)

1.0.0 (2019-09-11)

      ©2019, Mikhail Korotkov aka WLMike.

      |
      Powered by Sphinx 6.1.3

      |
      Page source


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Алфавитный указатель — документация apimoex 1.2.0</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/aiohttp.css" />

    <link rel="index" title="Алфавитный указатель" href="#" />
    <link rel="search" title="Поиск" href="search.html" />

<link rel="stylesheet" href="_static/custom.css" type="text/css" />

<link rel="canonical" href="https://wlm1ke.github.io/apimoexgenindex.html"/>

<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
<link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet">

Алфавитный указатель

 F
 | G
 | I

F

find_securities() (в модуле apimoex)

find_security_description() (в модуле apimoex)

G

get() (метод apimoex.ISSClient)

get_all() (метод apimoex.ISSClient)

get_board_candle_borders() (в модуле apimoex)

get_board_candles() (в модуле apimoex)

get_board_dates() (в модуле apimoex)

get_board_history() (в модуле apimoex)

get_board_securities() (в модуле apimoex)

get_index_tickers() (в модуле apimoex)

get_market_candle_borders() (в модуле apimoex)

get_market_candles() (в модуле apimoex)

get_market_history() (в модуле apimoex)

get_reference() (в модуле apimoex)

I

ISSClient (класс в apimoex)

apimoex

MOEX ISS API

Навигация

Начало работы

Установка

Пример использования реализованных запросов

Пример реализации запроса с помощью клиента

Справочник API

Функции-запросы

Справочная информация

Исторические данные по свечкам

Исторические данные по дневным котировкам

Реализация произвольного запроса

ISSClient

Список изменений

1.3.0 (2023-04-20)

1.2.0 (2020-02-03)

1.1.2 (2019-09-15)

1.1.1 (2019-09-13)

1.1.0 (2019-09-13)

1.0.2 (2019-09-12)

1.0.1 (2019-09-11)

1.0.0 (2019-09-11)

      ©2019, Mikhail Korotkov aka WLMike.

      |
      Powered by Sphinx 6.1.3


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />

    <title>Начало работы — документация apimoex 1.2.0</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/aiohttp.css" />

    <link rel="index" title="Алфавитный указатель" href="genindex.html" />
    <link rel="search" title="Поиск" href="search.html" />
    <link rel="next" title="Справочник API" href="api.html" />
    <link rel="prev" title="MOEX ISS API" href="index.html" />

<link rel="stylesheet" href="_static/custom.css" type="text/css" />

<link rel="canonical" href="https://wlm1ke.github.io/apimoexgetting_started.html"/>

<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
<link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet">

Начало работы¶

Установка¶

$ pip install apimoex

Пример использования реализованных запросов¶

История котировок SNGSP в режиме TQBR:

import requests

import apimoex
import pandas as pd

with requests.Session() as session:
    data = apimoex.get_board_history(session, 'SNGSP')
    df = pd.DataFrame(data)
    df.set_index('TRADEDATE', inplace=True)
    print(df.head(), '\n')
    print(df.tail(), '\n')
    df.info()

           BOARDID  CLOSE    VOLUME         VALUE
TRADEDATE
2014-06-09    TQBR  27.48  12674200  3.484352e+08
2014-06-10    TQBR  27.55  14035900  3.856417e+08
2014-06-11    TQBR  28.15  27208800  7.602146e+08
2014-06-16    TQBR  28.27  68059900  1.913160e+09
2014-06-17    TQBR  28.20  22101600  6.292844e+08

           BOARDID   CLOSE     VOLUME         VALUE
TRADEDATE
2019-09-04    TQBR  38.060  243010500  9.348435e+09
2019-09-05    TQBR  36.140  129366600  4.704949e+09
2019-09-06    TQBR  35.475   62389000  2.201887e+09
2019-09-09    TQBR  34.570   54331300  1.905837e+09
2019-09-10    TQBR  35.250   45966000  1.605849e+09

<class 'pandas.core.frame.DataFrame'>
Index: 1326 entries, 2014-06-09 to 2019-09-10
Data columns (total 4 columns):
BOARDID    1326 non-null object
CLOSE      1326 non-null float64
VOLUME     1326 non-null int64
VALUE      1326 non-null float64
dtypes: float64(2), int64(1), object(1)
memory usage: 51.8+ KB

Пример реализации запроса с помощью клиента¶

Перечень акций, торгующихся в режиме TQBR (описание запроса):

import requests

import apimoex
import pandas as pd

request_url = ('https://iss.moex.com/iss/engines/stock/'
               'markets/shares/boards/TQBR/securities.json')
arguments = {'securities.columns': ('SECID,'
                                    'REGNUMBER,'
                                    'LOTSIZE,'
                                    'SHORTNAME')}
with requests.Session() as session:
    iss = apimoex.ISSClient(session, request_url, arguments)
    data = iss.get()
    df = pd.DataFrame(data['securities'])
    df.set_index('SECID', inplace=True)
    print(df.head(), '\n')
    print(df.tail(), '\n')
    df.info()

          REGNUMBER  LOTSIZE   SHORTNAME
SECID
ABRD   1-02-12500-A       10  АбрауДюрсо
AFKS   1-05-01669-A      100  Система ао
AFLT   1-01-00010-A       10    Аэрофлот
AGRO           None        1    AGRO-гдр
AKRN   1-03-00207-A        1       Акрон

          REGNUMBER  LOTSIZE   SHORTNAME
SECID
YNDX           None        1  Yandex clA
YRSB   1-01-50099-A       10     ТНСэнЯр
YRSBP  2-01-50099-A       10   ТНСэнЯр-п
ZILL   1-02-00036-A        1      ЗИЛ ао
ZVEZ   1-01-00169-D     1000   ЗВЕЗДА ао

<class 'pandas.core.frame.DataFrame'>
Index: 264 entries, ABRD to ZVEZ
Data columns (total 3 columns):
REGNUMBER    255 non-null object
LOTSIZE      264 non-null int64
SHORTNAME    264 non-null object
dtypes: int64(1), object(2)
memory usage: 8.2+ KB

apimoex

MOEX ISS API

Навигация

Начало работы

Установка

Пример использования реализованных запросов

Пример реализации запроса с помощью клиента

Справочник API

Функции-запросы

Справочная информация

Исторические данные по свечкам

Исторические данные по дневным котировкам

Реализация произвольного запроса

ISSClient

Список изменений

1.3.0 (2023-04-20)

1.2.0 (2020-02-03)

1.1.2 (2019-09-15)

1.1.1 (2019-09-13)

1.1.0 (2019-09-13)

1.0.2 (2019-09-12)

1.0.1 (2019-09-11)

1.0.0 (2019-09-11)

      ©2019, Mikhail Korotkov aka WLMike.

      |
      Powered by Sphinx 6.1.3

      |
      Page source


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Поиск — документация apimoex 1.2.0</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/aiohttp.css" />

    <link rel="index" title="Алфавитный указатель" href="genindex.html" />
    <link rel="search" title="Поиск" href="#" />

<link rel="stylesheet" href="_static/custom.css" type="text/css" />

<link rel="canonical" href="https://wlm1ke.github.io/apimoexsearch.html"/>

<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
<link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet">

Поиск

    Для работы поиска включите JavaScript в браузере.

    Searching for multiple words only shows matches that contain
    all words.

  <form action="" method="get">
    <input type="text" name="q" aria-labelledby="search-documentation" value="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
    <input type="submit" value="искать" />

  </form>

apimoex

MOEX ISS API

Навигация

Начало работы

Установка

Пример использования реализованных запросов

Пример реализации запроса с помощью клиента

Справочник API

Функции-запросы

Справочная информация

Исторические данные по свечкам

Исторические данные по дневным котировкам

Реализация произвольного запроса

ISSClient

Список изменений

1.3.0 (2023-04-20)

1.2.0 (2020-02-03)

1.1.2 (2019-09-15)

1.1.1 (2019-09-13)

1.1.0 (2019-09-13)

1.0.2 (2019-09-12)

1.0.1 (2019-09-11)

1.0.0 (2019-09-11)

      ©2019, Mikhail Korotkov aka WLMike.

      |
      Powered by Sphinx 6.1.3