Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/asic/files/definitions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from asic.files.definitions.balcttos import BALCTTOS
from asic.files.definitions.pep import PEP
from asic.files.definitions.pme import PME
from asic.files.definitions.ptb import PTB
from asic.files.definitions.trsd import TRSD
from asic.files.definitions.tfroc import TFROC
from asic.files.definitions.tgrl import TGRL
Expand All @@ -29,6 +30,7 @@
FileKind.SNTIE: SNTIE,
FileKind.AFAC: AFAC,
FileKind.DSPCTTOS: DSPCTTOS,
FileKind.PTB: PTB,
}


Expand Down
6 changes: 2 additions & 4 deletions src/asic/files/definitions/adem.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@
class ADEM(AsicFile):
kind = FileKind.ADEM
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>adem)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[tT]{1}[xX]{1}[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Los archivos de demanda comercial"
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

Expand Down Expand Up @@ -104,8 +104,6 @@ def preprocess(self, target: Path | BytesIO | StringIO) -> pd.DataFrame:

filter = np.full(total.index.shape, True)
filter = filter & (total["CODIGO"].isin(["DMRE", "PRRE"]))
if self.agent is not None:
filter = filter & (total["AGENTE"] == self.agent.upper())

total = total[filter]
total["FECHA"] = pd.to_datetime(
Expand Down
4 changes: 2 additions & 2 deletions src/asic/files/definitions/aenc.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@
class AENC(AsicFile):
kind = FileKind.AENC
visibility = VisibilityEnum.AGENT
name_pattern = "(?P<kind>aenc)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Los archivos de demanda de agente por frontera"
description = ASIC_FILE_CONFIG[kind].description
# path = None
# year = None
# month = None
Expand Down
4 changes: 2 additions & 2 deletions src/asic/files/definitions/afac.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@
class AFAC(AsicFile):
kind = FileKind.AFAC
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>afac)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Muestra para cada uno de los agentes, todos los conceptos de la liquidación del Mercado Colombiano, con los cuales se pueden consolidar las Compras y Ventas Totales del Agente para un proceso de liquidación o ajuste mensual."
description = ASIC_FILE_CONFIG[kind].description
_format = FORMAT

@property
Expand Down
2 changes: 1 addition & 1 deletion src/asic/files/definitions/balcttos.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
class BALCTTOS(AsicFile):
kind = FileKind.BALCTTOS
visibility = VisibilityEnum.AGENT
name_pattern = "(?P<kind>BalCttos)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Los archivos de despacho de demanda por mercados R y NR, Nacional, TIE e Internacional"
Expand Down
4 changes: 2 additions & 2 deletions src/asic/files/definitions/dspcttos.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@
class DSPCTTOS(AsicFile):
kind = FileKind.DSPCTTOS
visibility = VisibilityEnum.AGENT
name_pattern = "(?P<kind>dspcttos)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Información de los contratos que fueron incluidos en el despacho del respectivo día, para cada agente según sea su posición en el contrato de comprador o de vendedor, para comercializadores."
description = ASIC_FILE_CONFIG[kind].description
_format = FORMAT

@property
Expand Down
4 changes: 2 additions & 2 deletions src/asic/files/definitions/pep.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
class PEP(AsicFile):
kind = FileKind.PEP
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>pep)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Contiene información de los precios de escasez promedio ponderado por sistema y por agente. Resolución 140 de 2017"
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

Expand Down
4 changes: 2 additions & 2 deletions src/asic/files/definitions/pme.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
class PME(AsicFile):
kind = FileKind.PME
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>PME)(?P<ordinance>140)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Contiene información de Insumos del calculo del Precio Marginal de escasez, según Resolución CREG 140/2017"
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

Expand Down
104 changes: 104 additions & 0 deletions src/asic/files/definitions/ptb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import logging
from io import BytesIO, StringIO
from pathlib import Path, PureWindowsPath

import numpy as np

# Third party imports
import pandas as pd

from asic import ASIC_FILE_CONFIG
from asic.files.file import AsicFile, FileKind, VisibilityEnum

# Local application imports

logger = logging.getLogger(__name__)

FORMAT = {
"type": "csv",
"sep": ";",
"encoding": "cp1252",
"dt_fields": {},
"dtype": {
"FECHA": str,
"PERIODO": int,
"PBNAL": float,
"DdaCom": float,
"HORA 01": float,
"DEM": float,
"PTB": float,
"OHEFx": float,
"OHEFy": float,
"OHEFz": float,
"GIx": float,
"GIy": float,
"GIz": float,
"GIv": float,
"GINAL_NDC": float,
},
}


class PTB(AsicFile):
kind = FileKind.PTB
visibility = VisibilityEnum.PUBLIC
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

@property
def path(self) -> PureWindowsPath:
return self._path

@property
def year(self) -> int:
return self._year

@property
def month(self) -> int:
return self._month

@property
def day(self) -> int | None:
return self._day

@property
def extension(self) -> str:
return self._extension

@property
def version(self) -> str | None:
return self._version

@property
def agent(self) -> str | None:
return self._agent

def preprocess(self, target: Path | BytesIO | StringIO) -> pd.DataFrame:
"""
PTB: es un archivo diario
versiones: TX2, TXR, TXF
"""
total = self.read(target)

total["FECHA"] = pd.to_datetime(
total["FECHA"],
format="%Y-%m-%d",
)

total = (
total.set_index(["FECHA", "PERIODO"])
.stack()
.reset_index()
)
total = total.rename(columns={"PERIODO":"NOMBRE HORA","level_2": "CODIGO", 0: "VALOR"})
total["HORA"] = total["NOMBRE HORA"]
total["HORA"] = pd.to_timedelta(total["HORA"], unit="h")
total["FECHA_HORA"] = total["FECHA"] + total["HORA"]

return_cols = ["FECHA_HORA", "CODIGO", "VALOR"]
return total[return_cols]

4 changes: 2 additions & 2 deletions src/asic/files/definitions/sntie.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
class SNTIE(AsicFile):
kind = FileKind.SNTIE
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>sntie)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Ajuste final de transacciones TIE, denominados Saldos Netos TIE, que se calcula a partir de la diferencia, de los precios informados por el Administrador del Mercado Exportador en la liquidación final, respecto a los valores obtenidos en la segunda liquidación."
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

Expand Down
5 changes: 3 additions & 2 deletions src/asic/files/definitions/tfroc.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
class TFROC(AsicFile):
kind = FileKind.TFROC
visibility = VisibilityEnum.AGENT
name_pattern = "(?P<kind>tfroc)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Los archivos de factores de perdidas aplicables a los consumos"
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

@property
Expand Down
4 changes: 2 additions & 2 deletions src/asic/files/definitions/tgrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@
class TGRL(AsicFile):
kind = FileKind.TGRL
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>tgrl)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Información general horaria que soporta las liquidaciones asociadas con los conceptos de desviación, compra/venta de contratos, restricciones, reconciliaciones, AGC, etc."
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

Expand Down
4 changes: 2 additions & 2 deletions src/asic/files/definitions/trsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@
class TRSD(AsicFile):
kind = FileKind.TRSD
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>trsd)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "" # TODO
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

Expand Down
5 changes: 3 additions & 2 deletions src/asic/files/definitions/trsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@
class TRSM(AsicFile):
kind = FileKind.TRSM
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>trsm)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Contiene información de indicadores económicos, energéticos y financieros."
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

@property
Expand Down
5 changes: 3 additions & 2 deletions src/asic/files/definitions/tserv.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@
class TSERV(AsicFile):
kind = FileKind.TSERV
visibility = VisibilityEnum.PUBLIC
name_pattern = "(?P<kind>tserv)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)"
name_pattern = ASIC_FILE_CONFIG[kind].name_pattern
location_pattern = ASIC_FILE_CONFIG[kind].location_pattern
location = ASIC_FILE_CONFIG[kind].location_template
description = "Contiene el soporte a la liquidación de servicios CND, SIC y FAZNI."
description = ASIC_FILE_CONFIG[kind].description

_format = FORMAT

@property
Expand Down
3 changes: 2 additions & 1 deletion src/asic/files/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class FileKind(str, enum.Enum):
SNTIE = "sntie"
AFAC = "afac"
DSPCTTOS = "dspcttos"
PTB = "ptb"

# LDCBMR = "ldcbmr"
# PUBFC = "pubfc"
Expand Down Expand Up @@ -107,7 +108,7 @@ class AsicFile(ABC):
name_pattern: str
location_pattern: str
location: str
description: str
description: str | None

@property
@abstractmethod
Expand Down
3 changes: 3 additions & 0 deletions tests/RUTA/PUBLICA/DEL/FTP/2025-04/PTB0401.txf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FECHA;PERIODO;PBNAL;DdaCom;DEM;PTB;OHEFx;OHEFy;OHEFz;GIx;GIy;GIz;GIv;GINAL_NDC
2025-04-01;20;359.984921882;11015609.18;10231103.04;359.984921882;0;0;0;0;1957324.73294819156381247981710532824565;8151609.67705180843618752018289467175435;122168.63;784506.14
2025-04-01;21;359.984921882;10851648.73;10062303.85;359.984921882;0;0;0;0;1957324.73294819156381247981710532824565;7982876.04705180843618752018289467175435;122103.07;789344.88
1 change: 1 addition & 0 deletions tests/TEST_ASIC_FILE_CONFIG.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
{"code":"trsm", "visibility": "public","name_pattern":"(?P<kind>trsm)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)","location_pattern":"/RUTA/PUBLICA/DEL/FTP/(?P<location_year>[0-9]{4})-(?P<location_month>[0-9]{2})/","description":"Contiene información de indicadores económicos, energéticos y financieros."}
{"code":"afac", "visibility": "public","name_pattern":"(?P<kind>afac)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)","location_pattern":"/RUTA/PUBLICA/DEL/FTP/(?P<location_year>[0-9]{4})-(?P<location_month>[0-9]{2})/","description":"Muestra para cada uno de los agentes, todos los conceptos de la liquidación del Mercado Colombiano, con los cuales se pueden consolidar las Compras y Ventas Totales del Agente para un proceso de liquidación o ajuste mensual."}
{"code":"tserv", "visibility": "public","name_pattern":"(?P<kind>tserv)(?P<name_month>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)","location_pattern":"/RUTA/PUBLICA/DEL/FTP/(?P<location_year>[0-9]{4})-(?P<location_month>[0-9]{2})/","description":"Contiene el soporte a la liquidación de servicios CND, s y FAZNI."}
{"code":"ptb", "visibility": "public", "name_pattern":"(?P<kind>ptb)(?P<name_month>[0-9]{2})(?P<name_day>[0-9]{2}).(?P<ext_versioned>[a-zA-Z0-9]+)","location_pattern":"/RUTA/PUBLICA/DEL/FTP/(?P<location_year>[0-9]{4})-(?P<location_month>[0-9]{2})/","description":"El PTB considera tres techos en las transacciones en bolsa cuando el precio de bolsa es mayor a cualquiera de los precios de escasez."}
11 changes: 11 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,15 @@
"version": "003",
"agent": "xxxc",
},
"ptb": {
"path": "/RUTA/PUBLICA/DEL/FTP/2025-04/PTB0401.txf",
"kind": "ptb",
"visibility": "public",
"year": 2025,
"month": 4,
"day": 1,
"extension": ".txf",
"version": "003",
"agent": None,
},
}
41 changes: 41 additions & 0 deletions tests/test_ptb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import pathlib

from pytest import fixture

from asic.files.definitions.ptb import PTB

from .conftest import ALL_FILES, TESTFILES


@fixture
def ptb_remote_path():
ptb_path = ALL_FILES["ptb"]["path"]
path = pathlib.PureWindowsPath(ptb_path)
return path


@fixture
def ptb_file(ptb_remote_path):
path = ptb_remote_path
file = PTB.from_remote_path(path)
return file


@fixture
def local_ptb_file(ptb_file: PTB, datafiles: pathlib.Path) -> pathlib.Path:
relative_path = ptb_file.path.relative_to(ptb_file.path.anchor)
local_file = datafiles / relative_path
assert local_file.is_file()
return local_file


@TESTFILES
def test_ptb_read(ptb_file: PTB, local_ptb_file):
data = ptb_file.read(local_ptb_file)
assert len(data) == 2


@TESTFILES
def test_ptb_preprocess(ptb_file: PTB, local_ptb_file):
long_data = ptb_file.preprocess(local_ptb_file)
assert len(long_data) == 24